In JSP EL enum value always empty [duplicate] - java

This question already has answers here:
How to reference constants in EL?
(12 answers)
Closed 6 years ago.
When trying to get an EL condition working I found that enum values are completely ignored. This seems to me contrary to the spec.
<c:out value='${com.foobar.data.BookingStatus.FAILED}' />
<c:out value='${BookingStatus.FAILED}' />
<c:out value='${com.foobar.data.BookingStatus.failed}' />
<c:out value='${BookingStatus.failed}' />
<c:if test="${empty BookingStatus.FAILED }">empty</c:if>
To my surprise these all evaluate to empty. Why is the Enum class not recognized?
This is happening in a current stable Tomcat instance.
Can this be a classpath issue? The Enum is used successfully in controller code but nowhere else in JSPs. It is supplied in a jar in the lib directory of the deployment.
UPDATE:
My intention is to compare a supplied Integer to an Enum's property like this:
<c:when test='${bookingInformation.bookingStatus eq BookingStatus.FAILED.code}'>
FOOBARFAIL
</c:when>
Unfortunately the value being checked can't be changed and will remain an Integer. The Enum looks as follow (simplified):
public enum BookingStatus {
COMPLETED(0), FAILED(1);
private final int code;
private BookingStatus(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
I want to avoid to hard code the Integer value of FAIL etc. and use the enum instead for the comparison.

That's because EL in its current version does not support accessing enums nor calling enum constants. This support is only available per EL 3.0.
It's unclear what your intent is, but it's good to know that you can compare enum properties as a String in EL. They are namely resolved as a String.
Assuming that you've a bean which look like this:
public class Booking {
public enum Status { NEW, PROGRESS, SUCCESS, FAILED }
private Status status;
public Status getStatus() {
return status;
}
}
Then you could test the Status.FAILED condition as follows:
<c:if test="${booking.status == 'FAILED'}">
Booking status is FAILED.
</c:if>
See also:
How to reference constants in EL?

As BalusC indicated, you cannot access enums using EL, however, you can do this:
<c:set var="enumFailed" value="<%=BookingStatus.FAILED%>"/>
<c:if test="${enumFailed.code == bookingInformation.bookingStatus}">
...
</c:if>
It would be ideal if bookingInformation.bookingStatus was an enum and not an int, but if re-factoring your app is out of the question due to its legacy nature, then my above example should help. You'd need a <c:set/> for each value of the enum (appears to just be two in your example).

You have to import the enum class in your jsp page. As far as you import it then you can refer to it. I wrote an example below.
My enum is the WebSettingType.
public enum WebSettingType {
SMTP_HOSTNAME("smtp_hostname"),
SMTP_PORT("smtp_port"),
SMTP_USERNAME("smtp_username");
private final String value;
private WebSettingType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
I have the websettings.jsp page that is uses a tag page etc.
<%#page import="my.package.WebSettingType"%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib prefix="t" tagdir="/WEB-INF/tags" %>
<t:admin>
<jsp:attribute name="css">
</jsp:attribute>
<jsp:attribute name="content">
<input type="text" name="${WebSettingType.SMTP_HOSTNAME.getValue()}"/>
</jsp:attribute>
</t:admin>

Related

How do I translate text in .java source files?

I have an enum like this
public enum CheckboxFeature {
Option1(" choose this"),
Option2(" or this"),
Option3(" maybe this"),
Option4(" lastly this");
#Getter
private final String text;
public static CheckboxFeature fromName(String v) {
for (CheckboxFeature c: CheckboxFeature.values()) {
if (c.name().equalsIgnoreCase(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
This shows the four options as checkboxes in the web view
<form:checkboxes items="${features}" path="enabledFeatures" itemLabel="text" delimiter="<br/>"/>
How can I translate these options? I use fmt:message for the rest of the translations in the web view.
I have tried
Option1(" <fmt:message key=\"text.test\"/>"),
and
Option1(" ${option1}"),
with
<fmt:message key="text.select" var="option1"/>
in the .jsp.
Neither of them work, so it seems it can't work this way. What is the correct way of translating the strings? Ideally using the fmt:message and i18n resources (lang.properties files) that are in place and working on the rest of the servlet?
Optimally, you get the resource key from the enum, and look that up.
public enum CheckboxFeature {
Option1("label.option1.key"),
Option2("label.option2.key"),
Option1("label.option3.key"),
Option2("label.option4.key");
private final String key;
[...]
I don't know how to nest a l10n lookup in the itemLabel attribute, so I would write something like:
<c:forEach items="Options.values()" var="current">
<form:checkbox path="selectedOptions" value="${current.name()}"/> <fmt:message key="${current.getKey()}"/>
</c:forEach>
1、CheckboxFeature add method like:
public static List<String> getAllCheckboxFeature(String v) {
return Arrays.asList(Option1.getText(),...Option4.getText());
}
2、than use the jstl like:
<c:forEach items="${options}" var="option">
<input type="checkbox" ="${option}">
</c:forEach>

Compare enum values in JSP

I've created an enum which looks like:
public enum BtsMode {
PROJECT_BTS("project_bts"), SERVICE_BTS("service_bts");
private String mode;
private BtsMode(String mode) {
this.mode = mode;
}
public String getMode() {
return mode;
}
public static BtsMode getBtsMode(Integer projectId) {
return projectId == 0 ? BtsMode.SERVICE_BTS : BtsMode.PROJECT_BTS;
}
};
This enum is a part of a class which contains other application level constants.
Based on the projectId value, I do other operations in my Spring/java application. On the UI side, I wish to use the same enum to compare the BtsMode type and do operations. I have searched the net and found that I can iterate over the enum and compare, but I have to check the specific BtsMode type.
Using the getBtsMode() method, I get the appropriate BtsMode and set it to the Spring ModelMap attribute.
BtsMode btsMode = BtsMode.getBtsMode(projectId);
modelMap.addAttribute("curBtsMode", btsMode);
In the JSP, I want to show hide the content depending on the BtsMode. Something like this,
<c:choose>
<c:when test="${curBtsMode eq BtsMode.PROJECT_BTS}">
<%-- Display elements specific to PROJECT_BTS --%>
</c:when>
<c:when test="${curBtsMode eq BtsMode.SERVICE_BTS}">
<%-- Display elements specific to SERVICE_BTS --%>
</c:when>
</c:choose>
I do not want to use scriptlets because we don't use them in our application. Is there any other way to achieve this?
Temporary Solution
Currently, as BtsMode enum having only two values, I can use it by setting in modelMap:
modelMap.addAttribute("projBtsMode", BtsMode.PROJECT_BTS);
modelMap.addAttribute("serviceBtsMode", BtsMode.SERVICE_BTS);
And accessing in JSP:
<c:if test="${curBtsMode eq projBtsMode}">
This works fine, but if there is any better solution, I would really appreciate it.
As long as you are using at least version 3.0 of EL, then you can import constants into your page as follows:
<%# page import="org.example.Status" %>
<c:when test="${dp.status eq Status.VALID}">
Some IDE dont understand this,so use alternative.
Helper Methods
public enum Status {
VALID("valid")
private final String val;
Status(String val) {
this.val = val;
}
public String getStatus() {
return val;
}
public boolean isValid() {
return this == VALID;
}
}
JSP:
<c:when test="${dp.status.valid}">
Try with a simple String:
<c:when test="${curBtsMode == 'PROJECT_BTS'}">
<%-- Display elements specific to PROJECT_BTS --%>
</c:when>
<c:when test="${curBtsMode == 'SERVICE_BTS'}">
<%-- Display elements specific to SERVICE_BTS --%>
</c:when>

how to pass values from jsp to java class

My Jsp page
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%#page contentType="application/xml" trimDirectiveWhitespaces="true" %>
<%# page import="com.raos.kookooivr.CallStatusValues" %>
<c:choose>
<c:when test='${(param.event == "Conference" || param.event == "Hangup" || param.event == "Disconnect") && requestScope.state == "conferenceStarted"}'>
<%
String session_id = request.getParameter("sid");
out.print(CallStatusValues.getsessionid(session_id));
String called_no = request.getParameter("cid");
out.print(CallStatusValues.getcalledno(called_no));
String actualtime = request.getParameter("total_call_duration");
out.print(CallStatusValues.getactualtime(actualtime));
String start_time = request.getParameter("start_time");
out.print(CallStatusValues.getstarttime(start_time));
String end_time = request.getParameter("time");
out.print(CallStatusValues.getendtime(end_time));
%>
</c:when>
</c:choose>
My Java Class
package com.raos.kookooivr;
public class CallStatusValues
{
public static String getsessionid(String session_id)
{
System.out.println(session_id);
return session_id;
}
public static String getcalledno(String called_no)
{
System.out.println(called_no);
return called_no;
}
public static String getactualtime(String actualtime)
{
System.out.println(actualtime);
return actualtime;
}
public static String getstarttime(String start_time)
{
System.out.println(start_time);
return start_time;
}
public static String getendtime(String end_time)
{
System.out.println(end_time);
return end_time;
}
}
I am getting 500 Error.
I am trying to pass the values of "String session_id = request.getParameter("sid");" to my java class and trying to print the session id
public static String getsessionid(String session_id)
{
System.out.println(session_id);
return session_id;
}
I need help to get the values from jsp to be printed using my java class. Example my sid is 123456. Then, that session id should be passed from my jsp file to my java class.
I'm afraid there are multiple problems with your code.
You can't use static methods - web servlets are multi-threaded, and need model class instances per thread (which usually maps to an instance per web session).
Your naming conventions are non-standard. The correct name for your session_id variable is sessionId and the getter should be getSessionId() - note the capitalization. This meets the Java Bean naming conventions.
The way you are coupling code to the model class (which incidentally has nowhere to store the data) is non-standard.
Writing java code in a JSP is generally regarded as code smell for new projects. It is more normal to just use EL and tags in the JSP and move any Java code out into the model and controller.
I suggest you download a simple working J2EE JSP servlet project and analyse how it works. Then start to modify it to suit your requirements. Something like http://crunchify.com/servlet-tutorial-getting-starting-with-jsp-servlet-example should get you started.
Unsure that you are doing what you want to do.
Here is what actually happens :
a client sends a request that ends in calling the JSP page
the servlet container calls the JSP with the context of the calling request
the JSP runs server side with the context of the calling request meaning that:
nothing has been rendered at that time
all the parameters "sid", "cid", etc. are those that the caller passed
if any of the required parameters were not passed in calling request, you get a NullPointerException that ends in an Error 500
BTW using a class with static methods that way from a JSP, is at least uncommon... It could make sense if you need to be able to to complex computations inside the JSP, but in that case, you'd better use a servlet to do the processing, store result in request attribute and forward to the servlet.

JSTL - Unable to access property of the object stored as session variable

I'm following the standard MVC architecture.
In my Controller I have the following code,
userDetailsBean = userDetailsDAO.getUserDetailsFromEmail(loginEmail);
session.setAttribute("userDetails", userDetailsBean);
The object userDetailsBean contains different methods like getFName(), getLName() etc. I'm accessing this object from the View file as follows,
<c:choose>
<c:when test="${sessionScope.userDetails != null}">
<li>
<a href="#userName">
${sessionScope.userDetails.getFName()}
</a>
</li>
</c:when>
<c:otherwise>
<li>
Log in/Register
</li>
</c:otherwise>
</c:choose>
I'm getting the following error from the above code,
HTTP Status 500 - /header.jsp(22,38) The function getFName must be used with a prefix when a default namespace is not specified
I searched a lot on the internet and tried many different suggestions like,
${sessionScope.userDetails.fName}
${sessionScope.userDetails.get(0).fName}
but none of it worked,
I'm using Tomacat 6 with JSTL 1.2 and Netbeans as IDE.
Any help is appreciated, thanks in advance!
You could read the JavaBean Specification. For links to it, look at the answer at Where is the JavaBean property naming convention defined?
Look at sections 8.3 and 8.8.
You should make your life easy and just use conventional names for your fields. But, if you choose not to do that, then consider the following bean.
package test;
public class BeanTest implements java.io.Serializable {
private String bHours = "ten";
private String RICK = "me";
private String Joe = "hello";
public BeanTest(){
}
public void setbHours(String bHours){
this.bHours = bHours;
}
public String getbHours(){
return bHours;
}
public void setRICK(String str){
RICK = str;
}
public String getRICK(){
return RICK;
}
public void setJoe(String str){
Joe = str;
}
public String getJoe(){
return Joe;
}
}
In a JSP you can use the following to access the data in the bean.
<jsp:useBean id="myBean" class="test.BeanTest" />
${myBean.RICK}
${myBean.joe}
${myBean.bHours}
<%=myBean.getbHours()%>

Transferring collection object from one jsp to another

I get the data from the database and store it in some collection object in one jsp(say One.jsp). I want this collection object to be available in another jsp(say Two.jsp). It might contain large data. So, I have used java bean for that in the following way.
public class BeanClass implements Serializable{
private HashMap<String,List<String>> myMap;
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public HashMap<String,List<String>> getMyMap() {
return myMap;
}
public void setData(HashMap<String,List<String>> myMap) {
this.myMap = myMap;
}
}
I am setting bean in One.jsp in the following way.
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:setProperty name="dataObject" property="myMap"/>
<%
dataObject.setData(myMapObj);
%>
But I get the following error:
Can't find a method to write property 'dataMap' of type 'java.util.HashMap' in a bean of type 'com.mypack.BeanClass'
Somewhere I found stating that we can't do the set for other things unless it is a string. Is there anyway that I can workaround it to make it work even for collection objects? So that I don't need to rollback lot of things that I have done. If not can someone please suggest how to transfer the collection object from one jsp to another? Example with snippet is appreciated.
Or is it that I am missing some extra configuration to make beans work?
Note: I might have used redirect() method, but here the navigation from One.jsp to Two.jsp is done by clicking on hyperlink(href)
EDIT:
Thanks to Alfreema. His solution worked after I had changed to setMyMap, but in Two.jsp I am facing issue. I try to display only some part of map like below. But it displays everything that is there in Map as if it shows when we use out.println(myMap); and it displays table at the very end of the page after printing the content of whole map.
Two.jsp:
<jsp:include page="header.jsp"/>
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:getProperty name="dataObject" property="myMap"/>
<%! HashMap<String,List<String>> gottenMap = null; %>
<%
gottenMap = dataObject.getMyMap();
%>
<table>
<tbody>
<%
String selectedPart = request.getParameter("part");
List<String> list = gottenMap.get(selectedPart);
for(int i=0; i<list.size(); i++)
{
%>
<tr>
<td colspan='2'><strong>
<%= list.get(i) %>
</strong></td>
</tr>
<%
}
%>
</tbody>
</table>
I am confused why it does like that without coding for printing the whole collection.
Change this:
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:setProperty name="dataObject" property="myMap"/>
<%
dataObject.setData(myMapObj);
%>
To this:
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:setProperty name="dataObject" property="data" value="${myMapObj}"/>
Your setter is called "setData(...)", not "setMyMap(...)". JSP is going to see property="data" and call setData(...).
So that will fix you up, but you didn't show us where you are setting myMapObj. We have to assume that you are setting that up correctly elsewhere and have made it available to the tag via a pageContext.setAttribute("myMapObj", myMapObj); call.
Side note: I recommend you rename the setData(..) method to setMyMap(...) to make it consistent with the getter getMyMap(...). If you do that, then you will need to change the property="..." back to "myMap", just like you had it.

Categories