Iteration in JSTL over map fails - jstl

Why code below fails with Property 'value' not found on type java.lang.String ?
<c:set var="map" scope="request">
<%= new HashMap<String, String>() {{
put("key1", "value1");
put("key2", "value2");
put("key3", "value3");
put("key4", "value4");
put("key5", "value5");
put("key6", "value6");
}} %>
</c:set>
<c:forEach var="item" items="${map}">
${item.value} <br/>
</c:forEach>
However it succeeds if servlets sets the map attribute and then forwards to JSP!!!

It seems that if value is in <c:set> body then string value is assigned to variable.
Code bellow works like a charm!
<c:set var="map" scope="request" value="<%= new HashMap<String, String>() {{ put(\"key1\", \"value1\"); put(\"key2\", \"value2\"); put(\"key3\", \"value3\"); put(\"key4\", \"value4\"); put(\"key5\", \"value5\"); put(\"key6\", \"value6\"); }} %>" />
<c:forEach var="item" items="${map}">
${item.key} <br/>
</c:forEach>

Use following code
<%=
HashMap hashMap= new HashMap<String, String>() {{
put("key1", "value1");
put("key2", "value2");
put("key3", "value3");
put("key4", "value4");
put("key5", "value5");
put("key6", "value6");
}}
request.setAttribute("map", hashMap);
%>
<c:forEach var="item" items="${map}">
${item.value} <br/>
</c:forEach>
You are mixing scriptlet with jstl type of coding, it is considered bad code practice see following link1, link2.
Also, see following for understanding jsp variable scope.

Related

how to make not display variables in url if there are no transmitted values

I made a board that can search and filter
However, even if do not use search and filter, the url will contain unnecessary values when click on the pagination
like this
http://localhost:8081/dictionary?filter=&keyword=&page=2
I think it's because fixed the variable in the a tag href
Is there a good way not to display it in url when there is no value?
dictionary.jsp
<%-- Pagination --%>
<c:forEach var="i" begin="${Paging.startPageNo }" end="${Paging.endPageNo }" step="1">
<c:choose>
<c:when test="${i == Paging.pageNo }">
<a class="active disabledLink" href="/dictionary?filter=${filter}&keyword=${keyword}&page=${i}"><c:out value="${i}"/></a>
</c:when>
<c:otherwise>
<c:out value="${i}"/>
</c:otherwise>
</c:choose>
</c:forEach>
<%-- Search --%>
<form action="dictionary">
<select name="filter">
<option selected value="total">total</option>
<option value="title">title</option>
<option value="content">content</option>
</select>
<input size=35 name="keyword"/>
<button type="submit">Search</button>
</form>
controller
String filter = request.getParameter("filter");
String keyword = request.getParameter("keyword");
filter = filter == null ? "" : filter;
keyword = keyword == null ? "" : keyword;
HashMap<String, Object> boardMap = new HashMap<String, Object>();
boardMap.put("Page", pagingService.getNowPage());
boardMap.put("PageSize", pageSize);
boardMap.put("classify", dictBoard);
boardMap.put("filter", filter);
boardMap.put("keyword", keyword);
List<HashMap<String, Object>> communityList = communityService.getBoardPage(boardMap);
model.addAttribute("Paging", pagingService.getPaging());
model.addAttribute("clist", communityList);
model.addAttribute("filter", filter);
model.addAttribute("keyword", keyword);
return "dictionary";

Why do am I getting error "java.lang.IllegalStateException" after putting <form:form> tag in jsp file of spring?

I have 2 tables, city and hotel_details in my database. I am trying to fetch the data from these tables and populating inside a form for registering the customer. But I am getting "java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute" as error.
JSP file
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<head>
<title>Search Hotels</title>
</head>
<body>
<h4>Search Hotels</h4>
<form:form action="search">
<table>
<tr>
<td>City:</td>
<td>
<form:select path="cities">
<form:options items="${cities}" />
</form:select>
</td>
</tr>
<tr>
<td>Hotel:</td>
<td>
<form:select path="hotels">
<form:options items="${hotels}" />
</form:select>
</td>
</tr>
<tr>
<td>Date:</td>
<td>
<input type="date" id="date" name="date">
</td>
</tr>
<tr>
<td colspan="3">
<input type="submit" value="Check Availability">
</td>
</tr>
</table>
</form:form>
Controller
#Controller
public class HomeController {
//need a controller method to show the initial HTML form
#Autowired(required=true)
private CityDAO cityDAO;
#Autowired(required=true)
private HotelDetailsDAO hotelDetailsDAO;
#RequestMapping("/")
public String showCheckAvailablityForm(Model theModel) {
// get customers from the dao
//List<City> theCities = cityDAO.getCities();
List<String> theCities = cityDAO.getCities();
Set<String> theHotels = hotelDetailsDAO.getHotels();
// add the customers to the model
theModel.addAttribute("cities", theCities);
theModel.addAttribute("hotels", theHotels);
//printing the data fetched
System.out.println("In HomeController showCheckAvailability method where city name is being fetched from city table");
theCities.forEach((n) -> System.out.println(n));
System.out.println("printing hotels");
for (String temp : theHotels) {
System.out.print(temp + " ");
}
return "checkAvailability-form";
}
#RequestMapping("/search")
public String searchResult(#RequestParam("cityName") String theCityName, #RequestParam("hotelName") String theHotelName,Model model) {
System.out.println("processed successfully");
return null;
}
}
When you use <form:form> attribute, it requires you to specify model object that should be bound to form tag. If you don't specify any model attribute default name is used as command.
Following is the description of form:form tag from spring-form.tld -
<attribute>
<description>Name of the model attribute under which the form object is exposed.
Defaults to 'command'.</description>
<name>modelAttribute</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>Name of the model attribute under which the form object is exposed.
Defaults to 'command'.</description>
<name>commandName</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
As you don't have any model object bound to form, try removing form:form tag and use HTML form tag and also make sure you match input parameter names with method parameter names. i.e -
<form action="search">
...
</form>

dynamic spring form:select element not bound to model

I am using Spring.AjaxEventDecoration to dynamically populate a drop down on my JSP but it is throwing an error as it cannot bind to the original model. I have been researching this for a while and I do not think this is possible but it seeems like it should be hence this post.. Help me out somebody!
OK My controller dumbed down looks like this,
#Controller
#RequestMapping(value = "/cis/crimeProperty/")
public class CrimePropertyController
{
#RequestMapping(value = "/manageView", method = RequestMethod.GET)
public ModelAndView managePropertyDetails(Long propertyId) throws DAOException
{
Map<String, Object> model = new HashMap<String, Object>();
CrimePropertyVO crimePropertyVO = new CrimePropertyVO();
model.put("crimePropertyVO", crimePropertyVO);
return new ModelAndView("cis.crime.property.edit", model);
}
#RequestMapping(value = "/changeItemList", method = RequestMethod.POST)
public ModelAndView retrieveItemList(String propertyClass)
{
Map<String, Object> model = new HashMap<String, Object>();
..call service to get list of items from class..
model.put("propertyItemList", propertyItemList);
return new ModelAndView("/cis/property/crime_property_item", model);
}
}
I am using tiles so my tile definition looks like this,
<definition name="cis.crime.property.edit" template="/WEB-INF/jsp/cis/property/manage_crime_property.jsp">
<put-attribute name="itemListFrag" value="/WEB-INF/jsp/cis/property/crime_property_item.jsp"/>
My (manage_crime_property.jsp) JSP looks like so,
<form id= "changeList" action="${pageContext.request.contextPath}/smvc/cis/crimeProperty/changeItemList" method="post">
<select id="propertyClassChange" path="propertyClass">
<option value="" label="-Please Select-"/>
<option value="CLO" label="CLOTHING"/>
<option value="TOL" label="TOOLS"/>
</select>
</form
<form:form modelAttribute="crimePropertyVO" action="${pageContext.request.contextPath}/smvc/cis/crimeProperty/saveProperty" method="post">
<table class="genericOutlinedTable" style="width: 100%;">
<tr>
<td><b>Item</b></td>
<td>
<tiles:insertAttribute name="itemListFrag" flush="true" ignore="false"/>
</td>
</tr>
<tr>
<td><b>Make</b></td>
<td><form:input path="propertyMake" size="20" maxlength="20"/></td>
<td><b>Model</b></td>
<td><form:input path="propertyModel" size="15" maxlength="15"/></td>
</tr>
</form:form>
<script type="text/javascript">
Spring.addDecoration(new Spring.AjaxEventDecoration({
elementId:'propertyClassChange',
event:'onchange',
formId:'changeList',
params: {fragments: 'itemListFrag'}
}));
My (crime_property_item.jsp) JSP fragment looks like this,
<span id="itemListFrag">
<form:select path="propertyItem">
<form:option value="" label="-Please Select-">
<c:forEach var="itemList" items="${propertyItemList}">
<form:option value="${itemList.propertyCode}" label="${itemList.propertyCode}" />
</c:forEach>
</form:select>
</span>
Its all configured correctly and when I change the first drop down it calls my controller changeItemList method which returns my JSP frag and list of items to make up the options but I get a server error ...
Neither BindingResult nor plain target object for bean name propertyItemavailable as request attribute
I've tried having just the options tags in my frag but that doesn't work and I've tried using the spring:bind tag and normal select but can't get that to work either.
Many Thanks in advance for any help with this.

Spring JSP Select List for Range of Numbers

I'm creating a time entry system where the user has the option of selecting the hour and minute via two separate drop down select boxes. So the hour box has the numbers 1-12 in it, and the minute box has 00-59.
This is part of a Spring 2.5 Java EE project.
I have this in my JSP, for example, to create the option values as part of a select dropdown list:
<% for( int i=1; i<=12; i++) { %>
<option value="<%=i %>" <%= Integer.parseInt(time1fromHr)==i?selected:"" %> />
<% } %>
The for loop generates all the hours and marks the currently selected hour as default. Well, it looks pretty ugly to me, mostly because there is quite a bit of Java code involved here and I was wondering if there is a more elegant solution to approaching this problem using JSP tags or the Spring library. I am passing in the currently set parameters via the ModelAndView object in Spring.
In your model you could pass a List of Integers for hours, and another for minutes. Then you could use the form:select tag.
<form:select path="hour">
<form:options items="${hours} />
</form:select>
If your command object for the form has the selected value set in the "hour" value, and the model contains 1-12 in the "hours" value, then it should render the select and take care of marking the appropriate option selected. Then you do the same for minutes.
If you don't want to go the spring form taglib direction, you could again place the hours in the model and use JSTL. Something like:
<c:forEach var="hour" items="${hours}">
<c:if test="${hour} == ${selectedHour}">
<option value="${hour}" selected="selected">${hour}</option>
</c:if>
<c:if test="${hour} != ${selectedHour}">
<option value="${hour}" >${hour}</option>
</c:if>
</c:forEach>
I know there's a better way to do the c:if part, maybe using a c:choose, but you get the gist. You have your selected value in selectedHour and your choices in hours in the model.
Yes there is, this part of Spring MVC:
#RequestMapping(value="/index.html",method=RequestMethod.GET)
public String form(ModelMap map) {
Map<String,String> country = new LinkedHashMap<String,String>();
country.put("US", "United Stated");
country.put("CHINA", "China");
country.put("SG", "Singapore");
country.put("MY", "Malaysia");
map.addAttribute("countryList", country);
return "index";
}
and then use:
<form:select path="country" items="${countryList}" />
don't forget to add Spring type Library to your page:
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
Use JSTL for comparison
<c:forEach var="hour" items="${hours}">
<c:if test="${hour == selectedHour}">
<option value="${hour}" selected="selected">${hour}</option>
</c:if>
<c:if test="${hour != selectedHour}">
<option value="${hour}" >${hour}</option>
</c:if>
</c:forEach>
OR
<c:forEach var="hour" items="${hours}">
<c:if test="${hour eq selectedHour}">
<option value="${hour}" selected="selected">${hour}</option>
</c:if>
<c:if test="${hour ne selectedHour}">
<option value="${hour}" >${hour}</option>
</c:if>
</c:forEach>

Binding multiple objects in a Spring form

I have problems with getting my JSP view right. What I intend to do is to send a List that contains questions and each question object is a text field and a List with alternatives.
My intention is to be able to edit multiple questions (both to be able to edit the text/name of the question and edit the containing alternatives).
My backing object is now sending an List question.
Here is my JSP which are failing with invalid property of bean class.
<form:form commandName="question">
<form:errors path="*">
<fieldset class="stdframe">
<legend>Question</legend>
</fieldset>
</form:errors>
<div class="stdframe">
<c:forEach var="q" items = "${question}" varStatus = "s">
<p><b>Question:</b></p>
<p><form:input size="67" path="${q.text}"/></p>
<br/>
${q.text}
<ul>
<c:forEach var="alternative" items = "${q.alternatives}" varStatus = "t">
${alternative.text}
<li><form:input path = "${alternative[$t.index].text}" /></li>
</c:forEach>
</ul>
<br/>
</c:forEach>
<input type="submit" class="submit" value="Save" />
<input type="button" class="button" onClick="back()" value="Back"/>
</div>
</form:form>
I have tried both ${q.text} and ${q[$s.index].text}. When I just print ${q.text} it shows the correct text for the question object. Same goes for alternative.
What can I do to correctly bind the form to the objects?
In addition when I store an object which contains a list of other object, will the list be stored itself in the database?
You may need to wrap your List in a simple object with the List as a field:
class MyListWrapper { List questions; } // etc.
If you use that as your command/form object, you should be able to do something like this in the JSP:
<form:form commandName="wrapper">
// ...
<c:forEach var="q" items = "${wrapper.questions}" varStatus = "s">
<p><b>Question:</b></p>
<p><form:input size="67" path="questions[${s.index}].text"/></p>
// ...
<c:forEach var="alternative" items = "${q.alternatives}" varStatus = "t">
${alternative.text}
<li><form:input path = "questions[${s.index}].alternatives[${t.index}].text" /></li>

Resources