JSTL conditional in Spring - java

I’m trying to use a JSTL conditional statement on a .jsp page in a Spring MVC app.
I have a model called user and an attribute called gender. The value of gender is displayed when I use this line in the .jsp:
${user.gender}
Specifically, in this case the value is ‘M’. But I want to display a literal ‘Male’ when the value is ‘M’. Based on the documentation I’ve found, my code should be:
<c:if test="${user.gender=='M'}">Male</c:if>
However, that doesn’t display anything. Any ideas what I’m doing wrong here?
The gender variable is defined as a String in my User model class.

I found a fix. As it turns out, my ${user.gender} value was for some reason getting padded with spaces. Thus, I had to trim off those spaces for the conditional to work. For that I used the JSTL trim function:
<c:set var="genderstring" value="${user.gender}"/>
<c:set var="genderstringtrimmed" value="${fn:trim(genderstring)}" />
Then I changed the conditional, which now works:
<c:if test="${genderstringtrimmed=='M'}">Male</c:if>

try
<c:if test="${user.gender.equals('M')}">Male</c:if>

Related

PHP's variable variables analog in JSTL

In PHP we can do the following with the help of Variable variables in PHP:
$privateVar = 'Hello!';
$publicVar = 'privateVar';
echo $$publicVar; // Hello!
Suppose we have the following chunk of Java code:
request.setAttribute("privateVar", "Hello!");
request.setAttribute("publicVar", "privateVar");
I've tried the following but an error occurs.
${${publicVar}}
Does anyone know how we can get value of privateVar via using only publicVar in JSP (JSTL)?
UPDATE 1:
I have a custom tag which allows to print a message if an object foo doesn't have a field bar.
I know I must catch exceptions in the case but I don't want to handle ones in JSP. I want to do it only in CustomTag file.
<%-- JSP file --%>
<ctf:tagName varName="foo.bar" />
<%-- CustomTag file --%>
<%# attribute name="varName" required="true" rtexprvalue="true"%>
<c:catch var="exception">
<c:set var="valX" value="${${varName}}" scope="page"/>
</c:catch>
<c:if test="${exception != null}">Can't find getter for the VAR in the OBJ.</c:if>
UPDATE 2:
JB Nizet gave me the answer and the following works well! :)
<c:set var="privateVar" value="Hello!" />
<c:set var="publicVar" value="privateVar" />
${pageScope[pageScope.publicVar]}
I don't think you can directly do this in the same way that you can in PHP. Instead you could change the attribute to use the value of the privateVar instead of the name, like this:
String privateVar = "Hello!";
request.setAttribute("privateVar", privateVar);
request.setAttribute("publicVar", privateVar);
This gives you access to the value under both names, which I think is the closest you'd get. No need to even put the attribute privateVar in the request if you are ultimately going to use publicVar on the JSP.
Ultimately you may want to rethink the design here as it doesn't really work in Java.
The basics:
That's not JSTL but Expression Language. And you should only use a single ${} evaluator. The code would be:
${publicVar}
More info:
StackOverflow Expression Language wiki
To your problem:
Expression Language doesn't allow that. You cannot have private attributes in any scope (page, request, session, application), so you can at most set the attribute twice with different names but the same value. But as you may note, this is useless.

Passing values in `<portlet:param>` using EL

I'm trying to pass a parameter with <portlet:actionURL> to a portlet in liferay, but it turns out that, using EL to pass values in not working, however, using JSP expression tag is working fine.
Here's my relevant code:
<%
ResultRow row = (ResultRow)request.getAttribute(WebKeys.SEARCH_CONTAINER_RESULT_ROW);
Course course = (Course) row.getObject();
long groupId = themeDisplay.getLayout().getGroupId();
String name = Course.class.getName();
String primaryKey = String.valueOf(course.getPrimaryKey());
%>
<liferay-ui:icon-menu>
<c:if test="<%= permissionChecker.hasPermission(groupId, name, primaryKey, ActionKeys.UPDATE)%>">
<portlet:actionURL name="editCourse" var="editURL">
<portlet:param name="resourcePrimaryKey" value="${primaryKey}"/>
</portlet:actionURL>
<liferay-ui:icon image="edit" message="Edit" url="${editURL}" />
</c:if>
</liferay-ui:icon-menu>
As you see, in <portlet:param> tag, I have used EL for passing value attribute. But it doesn't work, and I receive the value as 0 for "resourcePrimaryKey" in my action method, when I do:
long courseId = ParamUtil.getLong(request, "resourcePrimaryKey");
// courseId is 0 here
However, if I use JSP expression tag in place of EL, it works fine:
<portlet:actionURL name="editCourse" var="editURL">
<portlet:param name="resourcePrimaryKey" value="<%= primaryKey %>"/>
</portlet:actionURL>
Now, I get the required value for "resourcePrimaryKey".
Can anyone figure what's going on here? Surprisingly, EL at other place work fine, as you see - ${editURL} value for url attribute, is working fine, and redirecting to the corresponding url.
I came across this thread on apache mail archive regarding the same issue, but that doesn't really solve the problem.
A variable in the scriptlet cannot be used directly in an EL, you would first need to set it like:
<c:set var="primKey"><%=primaryKey %></c:set>
and use ${primKey} or set it as a request attribute:
request.setAttribute("primKey", primaryKey);
Clearly, better would be to directly use the expression.
Also regarding the ${editURL} working, it is a portlet jsp tag which sets the variable in the page context so that it is available to the EL.
Our el wiki is a good place to know these things, look out for the heading Make objects available to EL for this question :-)

How would you get a returned value from a JSTL tag back into an EL statement?

Basically I have a custom tag that handles querying a java object for me.
<c:set var="profit">
<ct:get-profit transaction="${transaction}"/>
</c:set>
Now the problem is that I want to use that value (which is a float in an if statement, which I do as so:
<c:when test="${profit > 0}">
When I do that though I end up getting the following error.
javax.el.ELException: Cannot convert -141.75 of type class java.lang.String to class java.lang.Long
I have no idea how I can make this work. I was under the impression that JSTL's would handle casting for you, is that incorrect? Either way, how would you go about making this work? Thanks
Can you try doing 0.00 instead of 0? <c:when test="${profit > 0.00}"> .
The reason you have to it is because 0 is getting treated as Long by the EL parser. However, "0.00" is getting treated as a float.
Everything which you set in the body of <c:set> is implicitly converted to String by Object#toString(). You'd like to use its value attribute instead which keeps the type unchanged.
I'd suggest to replace the <ct:get-profit> tag by an EL function. Since this tag doesn't seem to render any markup, you could do it as good (and better) with an EL function.
<c:set var="profit" value="${ct:getProfit(transaction)}" />
in combination with
public static float getProfit(Transaction transaction) {
// Implement.
}
For a more detailed example how to configure such a function, check the bottom of this answer.

How to access variable set by JSTL core in my JSP page?

In my webapp, I want to set a default cookie to store a locale of 'en_US'. I have functionality in place for the user to change this successfully.
However, I've removed a lot of scriptlets on my .jsp and replaced with some JSTL tags to set a default cookie value, but it doesn't seem to work. It seems that I can't access my ${lang} variable in my locale declaration. Am I missing something?
Here's my code:
<c:set var="lang" scope=="session">
<c:out value="${cookie['locale'].value}" default="en_US"/>
</c:set>
<fmt:setLocale value="${lang}" />
<fmt:bundle basename="com.foo.bar.app">
Edit
It seems as though I'm still having a problem. My setLocale call is not getting a good value. I tried a simple <c:out value="${lang}"/> and it is printing out ${lang} rather than a value, so I assume that my locale is being set to the variable name rather than the value. Any idea?
There's one = too much behind scope.

Can you put a <c:cout> tag inside the `value` attribute of a <c:set> tag?

I want to output the value of the xzy variable into the value of the abc variable.
<c:set var="abc" value="<c:out value="${xyz}"/>"/>
I'm getting an error (unterminated <c:set> tag) when I do this.
How do you do this?
No, you must have well-formed markup. <c:set/> can have body content instead of a value attribute though:
<c:set var="abc"><c:out value="${xyz}" /></c:set>
I would only use this to take advantage of the XML-escaping provided by <c:out/>. Otherwise it's simpler just to set the value="${xyz}".
What about
<c:set var="abc" value="${xyz}"/>
Remember, c:out is basically when you want to write text to the HTML page. In this case you just want to pass the value around, so keep it in variable land. Think of your java code doing this
String myString = System.out.println("12");
That is about what you are doing... :)

Categories