spring mvc requestmapping issues - spring

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();
}

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";
}

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.

model attribute on a second (redirected) JSP page not working, throws error - Spring MVC

My welcome page is Login.jsp. On submit it redirects to another page which enlists dummy transaction details of the logged in user.
please view this image link to see the login flow
However, when i try adding a form in the second page with a model attribute, it throws an error.
Login.jsp - form bit of code
<form:form method="POST" action="login2.html" modelAttribute="user" id="form">
<table>
<tr><td> <form:input path="user_id" placeholder="User ID:" value="" disabled="true"/></td></tr>
<tr><td><form:input path="email_id" placeholder="Email ID:" value="" /></td></tr>
<tr> <td> <form:password path="password" placeholder="Password" value="" /> </td></tr>
</table>
<input type="submit" value="Log-in"/>
</form:form>
Controller class action for login2.html
#RequestMapping(value = "/login2", method = RequestMethod.POST)
public ModelAndView login( #ModelAttribute("user") UserBean u1, BindingResult result) {
/*some code to call service class*/
/* lst is a list<Users>*/
model.put("t1", lst);
return new ModelAndView("save", model);
}
Save.jsp (redirected page)
<form:form method="POST" action="saveTransaction.html" modelAttribute="trans" id="form">
<table>
<tr>
<td><form:label path="transaction_id">Transaction ID:</form:label></td>
<td><form:input path="transaction_id" value="${i.transaction_id}" readonly="true"/></td>
</tr>
<tr>
<td><form:label path="user_id">User ID:</form:label></td>
<td><form:input path="user_id" value="${i.user_id}"/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Submit"/></td>
</tr>
</table>
</form:form>
<c:if test="${!empty t1}">
<table align="left" border="1">
<tr>
<th>transaction ID</th>
<th>User ID</th>
</tr>
<c:forEach var="i" items="${t1}">
<tr>
<td><c:out value="${i.transaction_id}"/></td>
<td><c:out value="${i.user_id}"/></td>
<td align="center">Edit | Delete</td>
</tr>
</c:forEach>
</table>
</c:if>
Controller class for action - saveTransaction.html
#RequestMapping(value = "/saveTransaction", method = RequestMethod.POST)
public ModelAndView saveTransaction( #ModelAttribute("trans") TransactionBeans t1, BindingResult result) {
/* some code */
/* lst is a list<TransactionDetails>*/
model.put("t1", lst);
return new ModelAndView("save", model);
}
TransactionBeans.java - bean class
public class TransactionBeans implements Serializable{
int user_id, transaction_id;
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public int getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(int transaction_id) {
this.transaction_id = transaction_id;
}
}
This code works with the form - it enlists all the data as i have shown in above screenshot. However, it throws an error with form modelAttribute. Please note, model attributes in both forms are different, binding different tables.
Error thrown:
root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'trans' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:178)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:198)
org.springframework.web.servlet.tags.form.LabelTag.autogenerateFor(LabelTag.java:129)
org.springframework.web.servlet.tags.form.LabelTag.resolveFor(LabelTag.java:119)
org.springframework.web.servlet.tags.form.LabelTag.writeTagContent(LabelTag.java:89)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:102)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:79)
org.apache.jsp.WEB_002dINF.views.save_jsp._jspx_meth_form_005flabel_005f0(save_jsp.java:208)
org.apache.jsp.WEB_002dINF.views.save_jsp._jspx_meth_form_005fform_005f0(save_jsp.java:153)
org.apache.jsp.WEB_002dINF.views.save_jsp._jspService(save_jsp.java:93)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:439)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
So does this mean a redirected page cannot have a different model from the calling page binding another set of data?
Thanks.
I can't see anywhere in your controllers the attributes "user" and "trans" passed into your models. Your views with modelAttribute seem to expect them and it is why you receive this error.
Also it would be great to see your GET method handlers as you only provide the ones associated with POST methods.
I'm maybe missing the point of what you are trying to achieve, but each view renders the model attributes you give to it.
Does-it help if I suggest the following for the controllers ?
#RequestMapping(value = "/login2", method = RequestMethod.GET)
public ModelAndView login(ModelMap model) {
model.put("user", new UserBean(0, "", ""));
return new ModelAndView("Login", model);
}
#RequestMapping(value = "/login2", method = RequestMethod.POST)
public ModelAndView loginPost( #ModelAttribute("user") UserBean u1, ModelMap model, BindingResult result) {
List<TransactionBeans> lst = service.getAll();
model.put("t1", lst);
//Display default transaction
model.put("trans", new TransactionBeans(0, 0));
return new ModelAndView("save", model);
}
#RequestMapping(value = "/saveTransaction", method = RequestMethod.POST)
public ModelAndView saveTransaction(TransactionBeans t1, ModelMap model,BindingResult result) {
service.save(t1);
List<TransactionBeans> lst = service.getAll();
model.put("t1", lst);
model.put("trans", t1);
return new ModelAndView("save", model);
}
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView edit(#RequestParam("id") String transactionId, ModelMap model) {
TransactionBeans trans = service.get(transactionId);
List<TransactionBeans> lst = service.getAll();
model.put("t1", lst);
model.put("trans", trans);
return new ModelAndView("save", model);
}
Good luck

Using object in JSP with Spring 4.0.7

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" %>

Resources