How to do numeric comparison but return false if can't parse to number? - jstl

Broadly: I want the test in a JSTL Core <c:when> tag to return false if either:
- A variable can't be parsed as a number; or
- Comparison of the same variable to a number-literal is false.
I know that the variable won't be parsable as a number in some cases; this should not cause an error.
Details of the use-case follow...
I have the following in a JSP file on a WebSphere Portal v7 server. This JSP is rendered by a Web Content portlet configured to use an IBM Web Content Manager JSP component.
<%# page session="false" buffer="none" %>
<%# page trimDirectiveWhitespaces="true" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/json" prefix="json" %>
<%# taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/portal-fmt" prefix="portal-fmt" %>
<%# taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/portal-core" prefix="portal-core" %>
<%# taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/portal-navigation" prefix="portal-navigation" %>
<%# page import="com.isw.portal.theme.SideNav" %> <%!
SideNav iswSideNav=SideNav.getInstance();
%>
<portal-navigation:navigation startLevel="${navTabsLevel}" stopLevel="${navTabsLevel+3}">
<%=iswSideNav.getNavHTML(wpsNavModel,wpsSelectionModel,request,response) %>
</portal-navigation:navigation>
This works consistently on normal page views.
However, when the Portal Search collection is being updated (which occurs automatically once every 6 hours and takes about 2 minutes), this JSP produces several exceptions every second.
The exceptions are always the same two repeated as below. The second exception always includes a stack trace, which I've omitted except for the line stating the NumberFormatException message.
NavigationTag E com.ibm.wps.engine.tags.NavigationTag setStartLevel EJPEJ0027E: StartLevel less than 1 is ignored.
NavigationTag E com.ibm.wps.engine.tags.NavigationTag setStartLevel EJPEJ0026E: StartLevel is not a valid number.
java.lang.NumberFormatException: For input string: ""
As these exceptions don't seem to cause any functional problems, I want to wrap the <portal-navigation:navigation> element inside a <c:choose> element, such that the navigation is rendered when navTabsLevel is parsable as a number and that number is >= 1, but otherwise show a 1-line warning.
How do I do this without causing a "string cannot be parsed to number" error?

You can use <c:catch> for that.
<c:catch var="exception">
<portal-navigation:navigation startLevel="${navTabsLevel}" ... />
</c:catch>
<c:if test="${not empty exception}">
Handle fail.
</c:if>
Alternatively, and better, create a custom EL function like matches(), isNumber(), etc.
<c:choose>
<c:when test="${my:isNumber(navTabsLevel)}">
<portal-navigation:navigation startLevel="${navTabsLevel}" ... />
</c:when>
<c:otherwise>
Handle fail.
</c:otherwise>
</c:choose>
There's at least nothing available in standard JSTL functions set for that.

Related

Bind a form object to a ModelAttribute with a prefix?

I have a legacy application that contains lots of forms from a previous framework that required a prefix for the entity. For example, an Item object with a name would have a form field of:
<input name="item.name" ... />
In my spring controller, I use a ModelAttribute as normal:
#ModelAttribute Item item
But the binding fails because spring does not expect the prefix for the item. Is there some way I can tell spring to ignore the prefix and bind without having to create a wrapper object or having to change the prefix from every form field?
If you are using jsp as your view, you will also need to add modelAttribute in your form as well, and make sure that you have declared getters for your form fields in Item object. Ex: getName()
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form id="new-item-form"
method="post"
modelAttribute="item" ...>
<input name="item.name" ... />
</form:form>
If you're using Thymeleaf , then you have to add its XML namespace to your html, and then you can access model attributes in views with Thymeleaf using Spring EL as follows:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
...
<p th:text="${item.name}">Name</p>
...
</html>

jstl conditional not working

I'm trying to separate my Java Code from my JSP files and I'm having a bit of a problem. I'm trying to find out whether the user is a guest or not and then printing the appropriate action EG login form or their Username.
Heres my index.jsp file:
<% if(view.guest) { %>
<%= "Scriptlet: Login Form Here" %>
<% } else { %>
<%= "Scriptlet: User Name Here" %>
<% } %>
<br/><br/>
<c:choose>
<c:when test="${view.guest eq true}">
JSTL Tag: Login Form Here
</c:when>
<c:otherwise>
JSTL Tag: User Name Here
</c:otherwise>
</c:choose>
This produces the following output:
Scriptlet: Login Form
JSTL Tag: User Name
As you can see the Scriptlet produces the expected results, but the JSTL tags produce the opposite. Infact if I reverse the JSTL's conditional to false (for debugging purposes) it still produces the same result "JSTL Tag: User Name"
Btw view.guest is a public boolean variable of the object view.
The JSP EL doesn't access local variables. It accesses attributes of the page, request, session or application scope. And it also assumes you're not using public fields (which should never be used), but respect the Java Bean conventions.
And, just as in Java, comparing a boolean with true is unnecessary. You just need
<c:when test="${view.guest}">
And the condition will evaluate to true if there is a page, request, session or application attribute named "view", having a public getGuest() or isGuest() method returning true.
If you didn't use scriptlets at all, you would never have local variables in your pages, and you would never have this problem.

How do I include JSTL variables from another file?

I would like to have a JSTL file of "constants" and reference them in other files.
e.g.
constants.jsp:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="colour" value="blue"/>
<c:set var="car">Audi</c:set>
Other file:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:import url="constants.jsp"/>
<p>I drive an ${car} which is ${colour}</p>
The code above (obviously) does not work. How can I get something similar to work?
Bonus points if I can use namespaces as well.
You could use an include directive:
<%#include file="/constants.jsp" %>
Or you could use a dynamic include, but then the variables would have to be stored in the request, rather than the page scope:
<jsp:include page="/constants.jsp" />
<c:set var="colour" value="blue" scope="request"/>
<c:set var="car" scope="request">Audi</c:set>
But the best way would probably be to put all these constants in an object, and store this object in the request (or session, or application) from a servlet or filter:
private class Constants {
private String color = "blue";
private String car = "Audi";
public String getColor() {
return color;
}
public String getCar() {
return car;
}
}
...
request.setAttribute("constants", new Constants());
...
<p>I drive an ${constants.car} which is ${constants.color}</p>

How to get sessionScope attributes on JSTL?

The task is to retrieve parameters from session via JSTL. The session parameter name is "programId" .
I tried:
<c:if test="${sessionScope.programId != null}" >
please execute
</c:if>
Then I tried:
<c:if test="${sessionScope:programId != null}" > please execute </c:if>
Here I get: The function applicationScope:programId is undefined
On top I have:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
Oracle has in examples:
http://docs.oracle.com/javaee/1.4/tutorial/doc/JSTL5.html
<c:if test="${applicationScope:booklist == null}" >
<c:import url="${initParam.booksURL}" var="xml" />
<x:parse doc="${xml}" var="booklist" scope="application" />
</c:if>
where applicationScope can be swapped by sessionScope.
again "trivialism" complexity drives me nuts. Why corp. examples never work?
Thank You Guys,
You're reading the wrong tutorial page. The <c:xxx> tags does not belong to the JSTL XML taglib which supports XPath syntax. Instead, it belongs to the JSTL Core taglib for which the proper tutorial page is here.
You need to use the normal ${bean.property} notation instead.
<c:if test="${applicationScope.booklist == null}">
<c:import url="${initParam.booksURL}" var="xml" />
<x:parse doc="${xml}" var="booklist" scope="application" />
</c:if>
In normal EL (not XPath!) syntax, the : identifies the start of an EL function. See also the JSTL Functions taglib for several EL function examples for which the tutorial page is here.
See also:
Our JSTL tag wiki page
Our EL tag wiki page
I don't find in your code you have set your variable programID somewhere in your SessionScope using EL something like the one shown below.
<c:set var="programID" value="SomeValue" scope="session"/>
If you indeed didn't set that variable, try setting it first like the above then try the following.
<c:if test="${sessionScope:programId != null}" > please execute </c:if>
It should work.
if you have set session in your controller
session.setAttribute("programID",someValue);
then you should try this
${sessionScope.programID} in your jsp
which is part of jstl core library
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
and if you are getting exception
"${sessionScope:programId != null}" contains invalid expression(s): javax.el.ELException: Failed to parse the expression [${sessionScope:programId != null}]
include jasper.jar in your lib folder
java brushup for basic concepts of java

spring mvc addAttribute to model, how to get it from jsp javascript

i have a controller with a model which i do addAttribute("show", "yes");
how do I retrieve this value inside javascript?...assuming I have jstl
Inserting it in a javasript would be the same as showing it in the html code of the jsp.
Try to do this:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
Show value is <c:out value="${show}"/>
if you can see the value in the JSP then JSTL is working. In any other case there may be another problem. For example that your configuration ignores EL. You can add this at the top of your JSP:
<%# page isELIgnored="false" %>
When you see the value in the HTML code then the JSTL is working in that case you can use it in Javascript. As your setting the value for tha variable "show" to yes it cannot be used as a boolean value (because it should be true or false). In this case you should use it as a string adding quotations
<script type="text/javascript">
var showVar = '<c:out value="${show}"/>';
alert("The variable show is "+showVar);
</script>
You can use Firebug to check that your javascript is working and you don't have any error on it.

Resources