JSTL foreach on enum - java

I have a contant list declared in java using enum type, that must appears in a jsp.
Java enum declaration :
public class ConstanteADMD {
public enum LIST_TYPE_AFFICHAGE {
QSDF("qsmldfkj"), POUR("azeproui");
private final String name;
#Override
public String toString() {
return name;
}
private LIST_TYPE_AFFICHAGE(String name) {
this.name = name;
}
public static List<String> getNames() {
List<String> list = new ArrayList<String>();
for (LIST_TYPE_AFFICHAGE test : LIST_TYPE_AFFICHAGE.values()) {
list.add(test.toString());
}
return list;
}
}
}
<select name="typeAffichage" id="typeAffichage">
<c:forEach var="type" items="${netcsss.outils.ConstanteADMD.LIST_TYPE_AFFICHAGE.names}">
<option value="${type}">${type}</option>
</c:forEach>
</select>
where as :
<select name="typeAffichage" id="typeAffichage">
<c:choose>
<c:when test="${catDecla ne null}">
<option
value="<%=catDecla.getCatDecla().getSTypeAffichage()%>"
selected="selected"><%=catDecla.getCatDecla().getSTypeAffichage()%></option>
</c:when>
</c:choose>
<%List<String> list = ConstanteADMD.LIST_TYPE_AFFICHAGE.getNames();
for(String test : list) {
%>
<option value="<%=test%>"><%=test%></option>
<%}%>
</select>
Works fine.
Is there a limitation on enum types ni foreach loop?

Another option is to use a <c:set/> tag like such:
<c:set var="enumValues" value="<%=YourEnum.values()%>"/>
Then just iterate over it as such:
<c:forEach items="${enumValues}" var="enumValue">
...
</c:forEach>
Your IDE should prompt you to import the YourEnum class.

The values method works fine, my mistake.
Indeed the problem was that I didn't put my list in the page scope of my jsp.
<% pageContext.setAttribute("monEnum", ConstanteADMD.ListTypeAffichage.values()); %>
...
<c:forEach var="entry" items="${monEnum}">
<option>${entry.type}</option>
</c:forEach>
No need of the getNames method

Another simple way can be:
<c:forEach items="<%=LIST_TYPE_AFFICHAGE.values()%>" var="entry">
<option>${entry.name }</option>
</c:forEach>
You need to import these:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page import="packagename.LIST_TYPE_AFFICHAGE"%>

You can create a method that returns Enum.values() if you cannot use values directly in your EL expression.
Remove the getNames() from inside your Enum and use a method like this instead somewhere else in your code.
public List<LIST_TYPE_AFFICHAGE> getNames() {
return new ArrayList<LIST_TYPE_AFFICHAGE>(Arrays.asList(LIST_TYPE_AFFICHAGE.values()));
}

The EL you are using in the items attribute on c:forEach is trying to call a static method on your enum types. I believe that EL only supports calls on instance methods.

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>

using an attribute of an arraylist in my jsp with struts-bean.tld

I have an issue using an attribute of an arraylist in my jsp.
The arraylist in my ActionForm :
private ArrayList<Account> accounts = new ArrayList<Account>();
The class declaration of the Account object in the Arraylist :
public class Account implements Serializable, Cloneable {
private String bic;
public String getBic() {
return bic;
}
public void setBic(final String newBic) {
bic = newBic;
}
}
The call in my jsp :
<bean:write name="BankAccountsActionForm"
property="accounts.get(0).bic" />
The console error :
javax.servlet.jsp.JspException: No getter method for property accounts.get(0).bic of bean BankAccountsActionForm
Do you have a solution or another way to do this?
I have a terrible alternative using a property accountbic1 directly in the form. But it induces lots of work behind to re affect all the temporary attributes to the real ArrayList.
If you have a collection of items in Struts 1.x, then use the <logic:iterate> tag.
Add the struts-logic.tld taglig on top of your JSP as follows:
<%# taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
Then, using <logic:present> and <logic:iterate> you can iterate your ArrayList as follows:
<logic:present name="accounts">
<logic:iterate id="account" name="accounts">
<bean:write name="account.bic" />
</logic:iterate>
</logic:present>
If you want to iterate a collection and access a particular index, use the indexId on <logic:iterate> like so:
<logic:present name="accounts">
<logic:iterate id="account" name="accounts" indexId="index">
<logic:equal name="index" value="0">
<bean:write name="account.bic" />
</logic:equal>
</logic:iterate>
</logic:present>
The same can be done using JSTL:
<logic:present name="accounts">
<logic:iterate id="account" name="accounts" indexId="index">
<c:if test="${index == 0}">
<bean:write name="account.bic" />
</c:if>
</logic:iterate>
</logic:present>
Make sure that Account class has a getter/setter method for attribute bic.
This is simply the error of getter and setter method. recode your getter and setter according to POJO standard as shown below:
Remove final from setter method and change your setter and getter method name as per POJO standard as shown below :
public String getBic() {
return bic;
}
public void setBic(String bic) {
this.bic = bic;
}
try some thing like:
<bean:write name="BankAccountsActionForm" property="accounts.get(1).bic" />
As it is a ArrayList not Array.
Make sure you have getter setter for accounts in in action class ** BankAccountsActionForm **
public List getAccounts ();
public void setAccounts(List acc);
Change your setter and getter method name as per POJO standard as shown below :
public String getBic() {
return bic;
}
public void setBic(final String newBic)
{ bic = newBic; }
It will work fine
remove final from setter method and try again and write it as follows
public void setBic(String bic )
{ this.bic = bic ; }

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.

In JSP EL enum value always empty [duplicate]

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>

Categories