How to parse spring post data in rest? - spring

I am developing an application in which i am using spring framework 3.1.1 and rest api. In it i have developed one rest controller which will on receiving "GET" request of url "/rest/host/{id}" will redirect the control to my view(form). Now after user fills up the form the posted data is also handled using rest. But in the method which i have written to handle post request all the parameters i am getting in one string which i want to parse and insert into the database. Can anybody tell which is the proper way to parse this spring data ? I can do it using String.split("&") but i don't think it is correct way to do that. Here is my code.
<form:form method="POST" action="/nagios-sms-1.0/rest/snooze/host/" commandName="snoozeBean">
<table width="100%" border="5" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table width="50%" border="5">
<tr>
<td colspan="3"></td>
</tr>
<tr>
<td width="30%"><form:label path="contactNumber">Enter host address</form:label></td>
<td width="30%"><form:input path="contactNumber" /></td>
<td />
</tr>
<tr>
<td width="30%"><form:label path="snoozeTimeoutValue">Enter Snooze time</form:label></td>
<td width="30%"><form:input path="snoozeTimeoutValue" /></td>
<td />
</tr>
<tr>
<td colspan="3">
<div id="buttons"
style="margin-left: 20Px; margin-right: 100px;">
<input type="submit" value="ok" /> <input type="reset" />
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
REST code..
1) GET handler method
#RequestMapping(value = "/host/{hostId}", method = RequestMethod.GET)
public String snoozeHost(#PathVariable int hostId, ModelMap map) {
Snooze snooze = new Snooze();
snooze.setHost_id(hostId);
map.put("snoozeBean", snooze);
return "host";
}
2) POST handler method
#RequestMapping(value = "/host", method = RequestMethod.POST)
#ResponseBody
public String snoozeHostOK(#RequestBody String payload) {
// i want to parse this payload data which contains my form fields.
System.out.println("data : " + payload);
return payload;
}
Any kind of help will be appreciated. Thanks in advance.

Instead of request body you can use #ModelAttribute and get all the form data bind in one pojo(snooze) filled by Spring Framework on post of the form.
You need to declare snooze in your get and post request mapped method as #ModelAttribute. That will let you get all your values from the form.
UPDATE
See your modified code here.
GET handler method
#RequestMapping(value = "/host/{hostId}", method = RequestMethod.GET)
public String snoozeHost(#PathVariable int hostId, #ModelAttribute Snooze snooze, ModelMap map) {
snooze.setHost_id(hostId);
return "host";
}
POST handler method
#RequestMapping(value = "/host", method = RequestMethod.POST)
#ResponseBody
public String snoozeHostOK(#ModelAttribute Snooze snooze) {
// you can use the setter methods of snooze object to retrieve the field values.
return payload;
}
Hope this helps you. Cheers.

Related

ModelAttribute not working with lists in spring

I want to bind a List using ModelAttribute. The list contains objects of type Transaction each of which contains transactionid (type int). This is my controller code:
#RequestMapping(value = "/approvecreditdebit.do", method = RequestMethod.POST)
public ModelAndView doActions(HttpServletRequest request,
#ModelAttribute("clc") Clc transactionList, BindingResult result,
ModelMap model) {
/*
* switch (action) { case "approve":
*/
System.out.println("Obj = " + transactionList.getClass());
System.out.println("Val = " + transactionList.getTransactionList());
Users users = new Users();
return new ModelAndView("internal","internal",users);
}
This is my jsp code:
<form:form action="approvecreditdebit.do" method="POST"
modelAttribute="clc">
<table border="1">
<tr>
<th>no</th>
<th>ID</th>
</tr>
<c:forEach items="${clc.transactionList}"
var="transaction" varStatus="status">
<tr>
<td>${status.index}</td>
<td><input name = "transaction[${status.index}].transactionId"
value="${transaction.transactionId}" /></td>
</tr>
</c:forEach>
</table>
<br>
<br>
<center>
<input type="submit" value="approve" />
</center>
</form:form>
This is the Clc class:
public class Clc{
private List<Transaction> transactionList;
public List<Transaction> getTransactionList() {
return transactionList;
}
public void setTransactionList(List<Transaction> transactionList) {
this.transactionList = transactionList;
}
}
The value of transactionList is not being set to the values received from the form. I receive the following error:
Request processing failed; nested exception is java.lang.NullPointerException
I tried searching for the solution on google and got a lot of solutions from stackoverflow but none of them seem to work.
Try something like this (notice the use of <form:input>). I just tried it on a simple Spring MVC app and it works (list is not null and has the values from the form when I try to access it in my POST method).
<c:forEach var="transaction" varStatus="status" items="${clc.transactionList}">
<tr>
<td>${status.index}</td>
<td><form:input path="transactionList[${status.index}].id" /></td>
</tr>
</c:forEach>

ModelAttribute returns null values in controller in Spring MVC

Ok, its time to seek help; I am sending a (shopping) Cart ModelAttribute to my jsp, allowing the user to edit the quantity, when the Model is POST to the controller the fields are null except the editable (quantity) field. I have researched for days on similar issues but nothing is matching. I am using spring 3.1.
Here is my controller on the GET and POST:
#Controller
public class CartController {
#Autowired
private Cart cart;
#RequestMapping(value = "/cart", method = RequestMethod.GET)
public String showCart(Model model) {
logger.debug("CartController.showCart() Cart: {}", this.cart);
model.addAttribute(cart);
return "cart/cart";
}
and POST
#RequestMapping(value = "/cart", method = RequestMethod.POST, params = "update")
public String update(#ModelAttribute("cart") Cart cart, BindingResult result, Model model) {
logger.debug("CartController.update() Cart: {}", cart);
return "cart/cart";
}
my jsp:
<div class="container MainContent">
<form:form method="POST" modelAttribute="cart">
<fieldset>
<legend>Cart</legend>
<table class="table">
<thead>
<tr>
<th>Product Name</th>
<th>Quantity</th>
<th>Product Price</th>
</tr>
</thead>
<tbody>
<c:forEach items="${cart.cartDetails}" var="cartDetail" varStatus="status">
<tr>
<td>${cartDetail.product.name}</td>
<td><form:input path="cartDetails[${status.index}].quantity" size="1" /></td>
<td>${cartDetail.price}</td>
</c:forEach>
<tr>
<b><td colspan="2" align="right"><spring:message code="order.total" /></b>
</td>
<td>${cart.totalCartPrice}</td>
</tr>
</tbody>
</table>
</fieldset>
<div></div>
<button id="order" name="order">
<spring:message code="button.order" />
</button>
<button id="update" name="update">
<spring:message code="button.update" />
</button>
</form:form>
</div>
and the log results for cart before on GET:
CartController.showCart() Cart: Cart [cartDetails=[CartDetail
product=com.Product#c26440[name=My Name],
quantity=1]], totalCartPrice=10.00]
and after updating the quantity from 1 to 3 in the jsp and then POST to the controller:
CartController.update() Cart: Cart [cartDetails=[CartDetail
[product=null, quantity=3]], totalCartPrice=null]
I've read several similar post here and on the Spring forum and tried different suggested solutions with no luck. It seems like my edited quantity results are getting bound to the Object correctly but why aren’t the others?
Assuming you have all the necessary fields in your Form object;
You have to specify the form fields and fill the value with your data.
<td>${cartDetail.product.name}</td>
will only print the result to the screen. If you want to bind it to your form you have to put it in a spring form input such as:
<form:input path="productName" value="${cartDetail.product.name}"/>
If you don't want it to be editable then you can put it into a hidden field but in the end you'll have to put it in a form element in the jsp and have a corresponding field in your form POJO
Seems other fields aren't bound, try to bind for example product name
<td>${cartDetail.product.name}
<form:hidden path="cartDetails[${status.index}].product.name" value="${cartDetail.product.name}"/></td>
I once spent a lot of time investigating a similar issue. Finally I found the culprit inside a Binder's initialization method:
#InitBinder
void initBinder(final WebDataBinder binder) {
binder.setAllowedFields("name", ...);
}
This method sets a restriction on fields that are allowed for binding. And all the other fields are unbound, naturally resulting in null values.
The other possible reason: incorrect setters in a Bean annotated with #ModelAttribute. For example, Object setName(String name) instead of void setName(String).

How to send back the model data from jsp to controller

I have a controller which sets few values to a model and sends to jsp. In jsp i need to show those values(as labels) along with additional values from user as input values. When i submit the jsp i only get valid values that user has entered and the values set earlier by controller is null.
JSP
<form:form
action="${pageContext.request.contextPath}/admin/deviceAction.html"
modelAttribute="deviceData">
<table class="gridtable" width="500px">
<tr>
<td>Device Name : </td>
<td>${deviceData.deviceName}</td>
</tr>
<tr>
<td>Model Name : </td>
<td>${deviceData.modelName}</td>
</tr>
<tr>
<td>Serial No : </td>
<td>${deviceData.serialNo}</td>
</tr>
<tr>
<td>Device Id : </td>
<td>${deviceData.deviceId}</td>
</tr>
<tr>
<td>Status : </td>
<td>${deviceData.statusCode}</td>
</tr>
<tr>
<td>Action : <span class="required">*</span></td>
<td>
<form:select path="deviceAction" >
<form:option value="" label="--- Select ---" />
<form:options items="${model.actionList}" />
</form:select>
</td>
</tr>
</table>
<input type="submit" value="Submit" id="btn_submit">
</form:form>
Controller:
public ModelAndView beforeSubmit() {
ModelAndView modelView = new ModelAndView();
DeviceData deviceData = new DeviceData();
deviceData.setDevicePk("123");
deviceData.setAccessToken("abcwetrwertewrtetr");
deviceData.setDeviceId("deferterterterterwtetetertg");
deviceData.setDeviceName("test");
deviceData.setEnrolledDate("7-8-13");
deviceData.setModelName("test1");
deviceData.setSerialNo("test2dsfgdfgdfg");
deviceData.setStatusCode("test3");
List<String> actionList = getActionList();
Map<String, List<String>> model = new HashMap<String, List<String>>();
model.put("actionList", actionList);
modelView.addObject("deviceData", deviceData);
modelView.addObject("model", model);
modelView.setViewName("admin/tokenSearchResult");
}
public ModelAndView afterSubmit() {
#ModelAttribute("deviceData") DeviceData deviceData, BindingResult result) {
logger.info("#################device datas are : " + deviceData.getDevicePk() + "###### " + deviceData.getDeviceAction());
return new ModelAndView();
}
deviceData.getDevicePk() is null
Only the drop down value is having valid value. Other values displayed in the screen are received as null.
Edit:
Till now i have found only one solution:
<form:input path="deviceName" readonly="true" />
But this way UI does not looks good. The editable and non editable values mixup in the screen. Looking for a better answer
Finally i am using hidden parameters to solve the problem.
Example:
<td>${deviceData.deviceName}</td>
is replaced by:
<td><form:hidden path="deviceName"</td>
By this way it helps me to avoid any css work(which i am not much comfortable)
If anyone get a better solution kindly post it here
You need to make them into form inputs using the Spring form tags in much the same way as you have for the form:select. If they are not editable by the user, you can always disable them.
You can simple hide those input. For example :
<input type="hidden" name="VehSeriesModelId" value="${vehDetailsVM.id }">
This way, you can get the data to the controller and the user will also not be able to edit the value. On the other hand, your form will also not show it :)

How to get data from two classes that are many-to-many, in the same edit form?

I am working with two classes that have a relationship many-to-many. I insert data in both tables, the relationship is usually registered in JoinTable. My question is, how to display the data from both tables in the same form?
Here is my controller:
#Controller
public class RecipeController {
#Autowired
private ReceitaService receitaService;
#RequestMapping(value = "/novaReceita.do", method = RequestMethod.POST)
public String createRecipes(#ModelAttribute("Receita") Receita receita, BindingResult resultReceita,
#ModelAttribute("Tag") Tag tag, BindingResult resultTag, #RequestParam String action, Map<String, Object> map) {
receita.getTag().add(tag);
receitaService.addReceita(receita);
map.put("receita", receita);
map.put("receitaList", receitaService.getAllReceita());
return "listRecipes";
}
Here is where I am having problems because I can only show data for a single table.
public String editForm(#PathVariable("id") int id, ModelMap map) {
map.addAttribute("receita", receitaService.getReceita(id));
return "updateRecipes";
}
Finally, the JSP page to display the data entered:
<c:url var="url" value="/receita/${receita.id}"/>
<form:form action="${url}" method="GET" commandName="receita">
<table width=80% >
<tr>
<td><strong>ID </strong></td>
<td><form:input path="id" disabled="true" class="input-small"/></td>
</tr>
<tr>
<td><strong>Title </strong></td>
<td><form:input path="titulo" class="input-xlarge"/></td>
</tr>
<tr>
<td valign=top><strong>Desc probl</strong></td>
<td><form:textarea path="desc_prob" class="input-xlarge" rows="3" /></td>
</tr>
<tr>
<td valign=top><strong>Desc soluc</strong></td>
<td><form:textarea path="desc_soluc" class="input-xlarge" rows="6" /></td>
</tr>
<tr>
<td><strong>Tag</strong></td>
<td> <form:input path="tag" disabled="true" class="input-small"/></td>
</tr>
</table>
</form:form>
What is missing to be able to show the data from both tables?
Thank's.
For single column/property you can use <form:input/>For Many to One you can use <form:select/>For One to Many you can use <form:select multiple='true'>In your case, you have to select a single ID first for the one side of the relationship which is receita and then display all the tags in that receita, so i think it counts as One to Many at that point. So in your case, try to use this tag:<form:select path="tag" multiple="true"/>

Passing object from JSP to spring controller

I have the below table in a .JSP page:
<form:form method="post" action="update.dtt" id="contactForms" modelAttribute="contactForms" >
<c:forEach items="${pList}" var="cf">
<tr>
<td align="center"><c:out value="${cf.fname}" /></td>
<td align="center"><c:out value="${cf.lname}" /></td>
<td align="center"><c:out value="${cf.cprovider}" /></td>
<td align="center"><c:out value="${cf.id}" /></td>
<td align="center"><c:out value="${cf.phone}" /></td>
<td><input type="submit" value="Update Contact"/></td>
</tr>
</c:forEach>
</form:form>
I'm iterating over the list (this is list of objects) and adding an Update Contact button for each record in the list. How can I pass on the particular instance (object) to the controller when the Update button is clicked?
The controller I have is as below. However I'm getting null.
#RequestMapping(value = "/user/update.dtt", method = RequestMethod.POST)
public String updateView(#ModelAttribute("contactForms") Banks bank, HttpServletRequest request, HttpServletResponse response, Model model) {
System.out.println("*First Name*" + bank.getFname());
//......
return "detailBank"; //name of jsp file
}
You'll need to have a hidden form field for each information you want to send to the server.
Since you have one button for each row, you should also have one form for each row. So the <form:form> and </form:form> lines should be inside the <c:forEach>, and not outside.
You need reference the instance by position, accessing to the element of the list by position.
list[i].name
list[i].surname
where list is the element in your pojo.

Resources