Using object in JSP with Spring 4.0.7 - spring

I'm trying to send object in a SpringController to the client. But it doesn't work.
I've read the same questions a bunch of times, but couldn't figure it out.
Here is my code :
#Controller
#RequestMapping(value = "/departs/{from}")
public class NextTrainController {
/** Handle nextTrains request with a destination specified */
#RequestMapping(value = "/{to}", method = RequestMethod.GET)
public String getNextTrainsToDestination(#PathVariable String from, #PathVariable String to,
#RequestParam(value = "date", required = false) Date date, Model model) {
// Date null means we leave now
if (date == null)
date = new Date();
/* debug */
List<TransilienTrain> trains = new ArrayList<TransilienTrain>(5);
TransilienTrain train = new TransilienTrain();
train.setMission("VIK30");
trains.add(train);
train = new TransilienTrain();
train.setMission("KOOPA34");
trains.add(train);
train = new TransilienTrain();
train.setMission("BOUGA90");
trains.add(train);
model.addAttribute("origin", from);
model.addAttribute("destination", to);
model.addAttribute("trains", trains);
return "departs";
}
My departs.jsp :
<c:if test="${not empty trains}">
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="col-sm-1">Départ</th>
<th class="col-sm-1">Train</th>
<th class="col-sm-2">Destination</th>
</tr>
</thead>
<tbody>
<c:forEach var="o" items="${trains}">
<tr>
<td>12h38*</td>
<td>${o.mission}</td>
<td>Paris Nord</td>
</tr>
</c:forEach>
</tbody>
</table>
<p>* Horraires théoriques</p>
</c:if>
My TransilienTrain class has a getter/setter for the mission attribute.
#Entity
#Table
public class TransilienTrain {
private String mission;
public String getMission() {
return mission;
}
public void setMission(String mission) {
this.mission = mission;
}
}
When I check the source code of the page, I do have the items in my list, but the o.mission isn't replaced with anything.

Found the solution. Thanks to #singh101.
Forgot to import the taglib definition:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

Related

How can I show custom error messages using Thymeleaf?

I'm trying to do CRUD operations with Spring. I'm using HTML and Thymeleaf on the frontend. I return the results of certain actions I have made and error messages, if any, using a custom class that I write. I don't have any problems so far. However, if an error occurs during these operations and I return this error through the class I wrote, I do not know how to display it on HTML using Thymeleaf.
I'm returning an object of this class type;
#Getter
#Setter
public class WarehouseAPIResponseHolder<T> {
private T responseData;
private HttpStatus httpStatus;
private WarehouseAPIResponseError error;
public WarehouseAPIResponseHolder(HttpStatus httpStatus) {
this.httpStatus = httpStatus;
}
public WarehouseAPIResponseHolder(T responseData, HttpStatus httpStatus) {
this.responseData = responseData;
this.httpStatus = httpStatus;
}
public WarehouseAPIResponseHolder(HttpStatus httpStatus,
WarehouseAPIResponseError error) {
this.httpStatus = httpStatus;
this.error = error;
}
}
My error class;
#Getter
#Builder
public class WarehouseAPIResponseError {
private String code;
private String message;
}
Example of an error;
if (CollectionUtils.isEmpty(warehouseEntities)) {
return new WarehouseAPIResponseHolder<>(HttpStatus.NOT_FOUND, WarehouseAPIResponseError
.builder()
.code("DATA_NOT_FOUND")
.message("No records found in the database.")
.build());
}
The method in my controller class;
#GetMapping
public String getAllWarehouses(Model model) {
model.addAttribute("listOfWarehouses",warehouseCRUDService.list().getResponseData());
return "warehouses";
}
My HTML code;
<div class="container my-2">
<h1 align="center">Warehouse List</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Code</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr th:each="warehouse : ${listOfWarehouses}">
<td th:text="${warehouse.id}"></td>
<td th:text="${warehouse.code}"></td>
<td th:text="${warehouse.name}"></td>
<td th:text="${warehouse.status}"></td>
</tr>
</tbody>
</table>
</div>
I am successfully listing, but if there is an error message I don't know how to display it. I did not use Spring validation methods. Is there any way I can do this in a simple way?
You can set the error on backend using model.addAttribute("errorMessage", error)
and then show it in an element if error exists. For example:
<span th:if="${errorMessage != null}" th:text=${errorMessage}/>

How to pass loop paramters from JSP to Spring Controller

I am having a loop on my JSP page and want to pass these values in my Spring Controller. On every click on Retry button in JSP, I need all values in my controller for further processing. The code which I tried so far is:
Any help much appreciated.
JSP File
<table class="gridtable">
<tr>
<th>Queue Name</th>
<th>Retry Attempt</th>
<th>Reason for failure</th>
<th>Action</th>
</tr>
<% int i=0; %>
<c:forEach var="queueRowDetail" items="${queueRowDetailList}">
<tr>
<td>${queueRowDetail.queueName}</td>
<td>${queueRowDetail.attempt}</td>
<td>${queueRowDetail.errorDetails}</td>
<td>
<form:form method="post" action="/retry" id="frmFailure_<%=i%>" modelAttribute="queueRowDetail"/>
<form:hidden path="queueName<%=i %>" value="${queueRowDetail.queueName}"/>
<form:hidden path="attempt<%=i %>" value="${queueRowDetail.attempt}"/>
<form:hidden path="errorDetails<%=i %>" value="${queueRowDetail.errorDetails} "/>
<input type="button" value="Retry" onClick="sendobj(<%=i%>)" />
</form>
</td>
</tr>
<% i++; %>
</c:forEach>
function sendObj()
<script>
function sendobj(i)
{
var x = document.getElementById("frmFailure_"+i);
alert(obj);
alert("frmFailure_"+i);
x.submit();// Form submission
}
</script>
QueueRowDetail Class
package com.gartner.gqueuefailureapi.model;
public class QueueRowDetail {
private String queueName;
private String errorDetails;
private int attempt;
private Object payLoad;
public String getQueueName() {
return queueName;
}
public void setQueueName(String queueName) {
this.queueName = queueName;
}
public String getErrorDetails() {
return errorDetails;
}
public void setErrorDetails(String errorDetails) {
this.errorDetails = errorDetails;
}
public int getAttempt() {
return attempt;
}
public void setAttempt(int attempt) {
this.attempt = attempt;
}
public Object getPayLoad() {
return payLoad;
}
public void setPayLoad(Object payLoad) {
this.payLoad = payLoad;
}
}
InderController.Java
#RequestMapping(value = "/retry", method = RequestMethod.POST)
public String retryMessage( #ModelAttribute("queueRowDetail")QueueRowDetail queueRowDetail, ModelMap model) {
model.addAttribute("queuename", queueRowDetail.getQueueName());
return "success";
}

Binding form parameters from JSP to spring controller

I know this is a question which has been asked before. I did look at those questions but I was still not able to resolve my problem and thus writing in on stackoverflow. I am trying to bind the form parameters from my form addArticles.jsp to the controller. On the controller when I do a system.out.println I only get the categoryId and do not get the categoryName. I am not sure what I am doing is incorrect and pretty amused.
addArticles.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Add Article</title>
</head>
<body>
<center>
<h2>Create New Article</h2>
<form:form action="/one2one/articles/save.do" method="POST" modelAttribute="command">
<table>
<tr>
<td><form:label path="id">Article ID</form:label></td>
<td><form:input path="id" value="${article.id}"></form:input></td>
</tr>
<tr>
<td><form:label path="title">Article Title</form:label></td>
<td><form:input path="title" value="${article.title}"></form:input></td>
</tr>
<tr>
<td><form:label path="description">Article Description:</form:label></td>
<td><form:input path="description" value="${article.description}" cssStyle="width: 150px;"></form:input></td>
</tr>
<tr>
<td><form:label path="category.categoryId">Category Type</form:label></td>
<td><form:select path="category.categoryId" cssStyle="width: 150px;">
<option value="-1">Select a type</option>
<c:forEach items="${categories}" var="category">
<option <c:if test="${category.categoryName eq article.category.categoryName}">selected="selected"</c:if>
value="${category.categoryId}">${category.categoryName}</option>
</c:forEach>
</form:select>
</td>
</tr>
<tr>
<td><form:label path="keywords">Article Keywords:</form:label></td>
<td><form:input path="keywords" value="${article.keywords}"></form:input></td>
</tr>
<tr>
<td><form:label path="content">Article Content:</form:label></td>
<td><form:input path="content" value="${article.content}"></form:input></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="SAVE"/></td>
</tr>
</table>
</form:form>
</center>
</body>
</html>
ArticlesController.java
package com.java.bricks.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.java.bricks.model.Article;
import com.java.bricks.model.Category;
import com.java.bricks.service.ArticleService;
import com.java.bricks.service.CategoryService;
#Controller("articlesController")
#RequestMapping(value="/articles")
public class ArticlesController {
#Autowired
private ArticleService articleService;
#Autowired
private CategoryService categoryService;
#RequestMapping(value="/list", method=RequestMethod.GET)
public ModelAndView listArticles(#ModelAttribute("command") Article article, BindingResult bindingResult){
Map<String,Object> model = new HashMap<String,Object>();
model.put("articles", articleService.listArticles());
return new ModelAndView("articlesList",model);
}
#RequestMapping(value="/add",method=RequestMethod.GET)
public ModelAndView addArticle(#ModelAttribute("command") Article article, BindingResult bindingResult) {
Map<String,Object> model = new HashMap<String,Object>();
model.put("articles", articleService.listArticles());
model.put("categories", categoryService.listCategories());
return new ModelAndView("addArticle",model);
}
#RequestMapping(value="/save",method=RequestMethod.POST)
public ModelAndView saveArticle(#ModelAttribute("command") Article article, BindingResult bindingResult) {
Map<String,Object> model = new HashMap<String,Object>();
System.out.println("----------------------");
System.out.println(article.getCategory());
System.out.println(article.getCategory().getCategoryName());
System.out.println(article.getCategory().getCategoryId());
articleService.addArticle(article);
model.put("articles",articleService.listArticles());
return new ModelAndView("addArticle",model);
}
}
when I click save the first 4 lines of the SOP statements are
System.out.println(article.getCategory());
output: Category [categoryId=29, categoryName=null]
System.out.println(article.getCategory().getCategoryName());
null
System.out.println(article.getCategory().getCategoryId())
29
I am not sure why the categoryName is not populated in the controller.
Article.java
package com.java.bricks.model;
public class Article {
private Long id;
private String title;
private String description;
private String keywords;
private String content;
private Category category;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getKeywords() {
return keywords;
}
public void setKeywords(String keywords) {
this.keywords = keywords;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
}
You aren't going to get the category name in the form's content because the category's name is being used a the label for the option. Only the value gets bound. This is your binding path="category.categoryId". You aren't binding anything to path="category.categoryName" so it's going to be null.
So in your controller you have to get the category by its ID. If you want to do some automatic custom conversion, that is a separate question.
Here's a nice article on entity conversion.

What is the purpose of spring model addObject(Object attributeName)?

In spring mvc, when creating a ModelAndView there's a method called addObject(Object attributeName) single parameter, and I don't understand how to make use of it. I also see model.addAllObjects(Map<String, ?> object).
How can I get that map in jsp? Or what is the purpose of those methods? I only know how to make use of model.addObject("car", new Car()) because is like defining servlet parameters. I found this information in spring but I don't really understand it.
Spring addObject and addAllObjects
please check the example below. i have shed how to use addObject(Object attributeValue) as well as addAllObjects(Map<String, ?> modelMap).
Car.java
public class Car {
private String regNo;
private String model;
private String year;
public String getRegNo() {
return regNo;
}
public void setRegNo(String regNo) {
this.regNo = regNo;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
}
PageContent.java
public class PageContent {
private String headerName;
public String getHeaderName() {
return headerName;
}
public void setHeaderName(String headerName) {
this.headerName = headerName;
}
}
Controller Method
#RequestMapping(value = "/showCars", method = RequestMethod.GET)
public ModelAndView showApp() {
ModelAndView modelAndView = new ModelAndView();
//adding a single attribute for the modelMap
PageContent pageContent = new PageContent();
pageContent.setHeaderName("All Cars - From Controller");
modelAndView.addObject(pageContent);
List<Car> carList = new ArrayList<>();
Car car1 = new Car();
car1.setModel("Toyota");
car1.setRegNo("223456");
car1.setYear("2005");
Car car2 = new Car();
car2.setModel("Mazda");
car2.setRegNo("24244");
car2.setYear("2015");
Car car3 = new Car();
car3.setModel("Nissan");
car3.setRegNo("4465757");
car3.setYear("2013");
carList.add(car1);
carList.add(car2);
carList.add(car3);
Map<String,Object> allObjectsMap = new HashMap<String,Object>();
allObjectsMap.put("allCarObjects", carList);
//adding a set of objects for the model map
modelAndView.addAllObjects(allObjectsMap);
modelAndView.setViewName("CarView");
return modelAndView;
}
CarView.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<title>ModelAttribute Example</title>
</head>
<body>
<h1>${pageContent.headerName}</h1>
<table>
<tr>
<th>Model</th>
<th>Registration No</th>
<th>Year of Manufacture</th>
</tr>
<c:forEach var="car" items="${allCarObjects}">
<tr>
<td><c:out value="${car.model}" /></td>
<td><c:out value="${car.regNo}" /></td>
<td><c:out value="${car.year}" /></td>
</tr>
</c:forEach>
</table>
</body>
</html>
Hope this will helpful for you!
well,the first method addObject which would invoked when forward happend and brings the data to jsp.Then you can iterate the data in your jsp with jstl or something else.The method addAllObjects is just a multiple type of addObject,just like map's method put and putAll.

spring mvc requestmapping issues

i'm working in a spring mvc app (im new in spring mvc).
this is my controller:
#Controller
#RequestMapping("/prueba2")
public class controller2 {
Stock stock=new Stock();
List stockList=new ArrayList<Stock>();
ApplicationContext appContext = new ClassPathXmlApplicationContext("spring/config/BeanLocations.xml");
StockBo stockBo = (StockBo)appContext.getBean("stockBo");
#RequestMapping(method = RequestMethod.GET)
public Stock returnCustomer(ModelMap model) {
stock=stockBo.findByStockCode("7668");
model.addAttribute("miStock", stock);
return stock;
}
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody
List<Stock>returnAll(ModelMap model) {
stockList=stockBo.findAll();
System.out.println("lista objetos--->"+stockList.toString());
model.addAttribute("listaStock", stockList);
return stockList;
}
public StockBo getStockBo() {
return stockBo;
}
public void setStockBo(StockBo stockBo) {
this.stockBo = stockBo;
}
}
this is my view:
<%# taglib prefix="c"
uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
<h1>Message : "Por fin funciona!!!"</h1>
<table border="1">
<tr>
<th>Codigo Stock</th>
<th>Nombre Stock</th>
</tr>
<tr>
<td>${miStock.stockCode}</td>
<td>${miStock.stockName}</td>
</tr>
</table>
<h1>Tabla con lista de stock</h1>
<table>
<tr>
<th>Codigo Stock</th>
<th>Nombre Stock</th>
</tr>
<c:forEach items="${listaStock}" var="stock">
<tr>
<td>
${stock.stockCode}
</td>
<td>
${stock.stockName}
</td>
</tr>
</c:forEach>
</table>
<ul>codigo stock
<c:forEach items="${listaStock}" var="stock">
<li> <c:out value="${stock.stockCode}"></c:out> </li>
</c:forEach>
</ul>
</body>
</html>
what i want to do is to show 2 tables in the same JSP, i dont want to go to a different page to show each table, but i dont understand very well how to use the "requestmapping" to make it work.. now is just showing me the first table.
If you need access to the stock list as well as the individual stock item in the same JSP, then just add the stock list to the model.
#RequestMapping(method = RequestMethod.GET)
public Stock returnCustomer(ModelMap model) {
stock = stockBo.findByStockCode("7668");
model.addAttribute("miStock", stock);
model.addAttribute("listaStock", stockBo.findAll()); // Add the list to model
return stock;
}
Alternatively you can set it as a separate method which will save on duplication if it's used in many methods within the same controller.
#RequestMapping(method = RequestMethod.GET)
public Stock returnCustomer(ModelMap model) {
stock = stockBo.findByStockCode("7668");
model.addAttribute("miStock", stock);
return stock;
}
#ModelAttribute("listaStock")
public List<Stock> getAllStock() { // Called and set by Spring automatically
return stockBo.findAll();
}

Resources