Required String parameter 'newPassword' is not present - spring-boot

SOLVED
We've solved it. The form that the backend requires data was param, so the form that the vue sends was changed to param, not data!
I'm making a password change page.
Meanwhile, I got an error that there was no old password, new password data but I definitely transferred the data from Vue through axios.
There were answers to 'required=false', so I tried oldpassword, but here's the result.
However, we took 'required= true' because we believe newpassword, oldpassword is essential data for this approach.
When using post-man or swagger, the password is changed signaling 200 normally.
I thought there might be a problem with 'patch', so I tried 'put', but the error didn't change.
frontend
<div class="input-with-label">
<input v-model="newpassword" id="newpassword" placeholder="새 비밀번호를 입력하세요." :type="passwordType" />
<label for="newpassword">새 비밀번호</label>
<div class="error-text" v-if="error.newpassword">{{error.newpassword}}</div>
</div>
<form #submit.prevent="changepassword" #submit="checkForm">
<div v-if="activeButton() && !isSubmit">
<!-- <button #click="PopUpEmailModal" class="btn-bottom" >가입하기</button> -->
<button class="btn-bottom">변경하기</button>
</div>
<div v-else>
<button class="btn-bottom disabled" >변경하기</button>
</div>
</form>
import axios from 'axios'
export default {
name:'ChangePassword',
data: ()=> {
return{
email:"",
oldpassword:"",
newpassword:"",
isSubmit: true,
error: {
newpassword: false,
},
passwordType: "password",
passwordSchema: new PV(),
}
},
created() {
this.passwordSchema
.is()
.min(8)
.is()
.max(100)
.has()
.digits()
.has()
.letters();
},
watch: {
newpassword: function(v) {
this.checkForm();
},
},
methods:{
changepassword(){
axios({
url:'http://127.0.0.1:8080/account/changePassword',
method:'patch',
data:{
email: this.email,
oldPassword: this.oldpassword,
newPassword: this.newpassword,
},
})
.then(res=>{
console.log(res)
this.$router.push({ name:'Login' })
})
.catch(err=>{
console.log(typeof this.oldpassword)
console.log(this.oldpassword)
console.log(this.newpassword)
console.log(this.email)
console.log(err)
})
},
}
backend
#PatchMapping("/account/changePassword")
#ApiOperation(value = "비밀번호변경")
public Object changePassword(#RequestParam(required = false) final String oldPassword,
#RequestParam(required = true) final String newPassword,
#RequestParam(required = true) final String email){
Optional<User> userOpt = userDao.findByEmail(email);
if(!passwordEncoder.matches(oldPassword, userOpt.get().getPassword())){
throw new IllegalArgumentException("잘못된 비밀번호입니다.");
}
User user = new User(userOpt.get().getUid(), userOpt.get().getNickname(), email,
passwordEncoder.encode(newPassword), userOpt.get().getIntroduction(), userOpt.get().getThumbnail(), userOpt.get().getRoles());
userDao.save(user);
final BasicResponse result = new BasicResponse();
result.status = true;
result.data = "success";
ResponseEntity response = null;
response = new ResponseEntity<>("OK", HttpStatus.OK);
return response;
}

I believe you are using #RequestParam annotations but you are not sending any params in the URL from the frontend, hence the 400 error.
Since you are using Patch/Put I would suggest you change your changePassword function to take a dto. And since you are already sending data in the body from frontend so no change needed there.
For example
public Object changePassword(#RequestBody #Valid ChangePasswordDto changePasswordDto){
// your logic
}
Then create a ChangePasswordDto class with #Required on properties that are required.
public class ChangePasswordDto{
private String email;
private String newPassword;
private String oldPassword;
#Required
public void setEmail(String email) {
this.email= email;
}
#Required
public void setOldPassword(String oldPassword) {
this.oldPassword= oldPassword;
}
#Required
public void setNewPassword(String newPassword) {
this.newPassword= newPassword;
}
// corresponding getters
}

Related

vue how to post list with files to spring

Srping boot 2.x and vue 2.x.
My UI looks like(not the complete picture for simplicity) :
my java bean is:
public class Attachment {
private Integer eaId;
private Integer eId;
private String description;
private MultipartFile file;
//setters and getters
}
public class Booking {
private Integer id;
private String eNo;
private List<Attachment> attachmentList;
//some other fields
}
Each attachment item contains file and file description.
My front-end is:
<tr v-for=" (a, index) in eb.attachmentList" v-bind:key="index">
<td><input type="text" v-model="a.description" /></td>
<td><input type="file" v-on:change="selectFile(index, $event)" /></td>
<td><i class="far fa-trash-alt fa-lg" v-on:click="delAttachment(index)" style="color: red"></i>
</td>
</tr>
my spring controller is:
#PostMapping("/upload")
public Booking upload(#ModelAttribute Booking b) {
//....
}
the vue code is:
var vm = new Vue({
el: '#test',
data() {
return {
eb: {
'attachmentList': []
}
}
},
methods: {
selectFile(index, e) {
this.eb.attachmentList[index].file = e.target.files[0];
},
saveTest() {
var formData = new FormData();
//how to populate formData ?
axios.post("/tf/upload",
formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(function() {
//....
})
.catch(function(error) {
//...
});
}
}
});
I want to post this form data to spring controller with axios, that is convert form data to java bean Booking and the file list of form to List<Attachment> attachmentList of Booking.
It seems that I have to use FormData, right?
My problems is:
How to populate the FormData in my case?
If just upload file, I can use formData.append('file', file) then
post it with header multipart/form-data directly.
But now there are a few file list and each file associated with its description. I don't know how to do such that I can get the form data in my spring controller.
In Vue side:
First, you need to create a new object of type FormData and append to it a reference for the input element that you are appending the file to.
HTML:
<input type="file" #change="processFile($event)">
Vue:
methods: {
processFile(event) {
this.myFile = event.target.files[0]
}
}
This will do myFile variable hold a reference to the appended file.
When the time to upload comes:
const formData = new FormData();
formData.append('attribute-name-spring-expects', this.myFile, this.myFile.name);
// other attributes
Then, send this form data with axios like this:
const requestConfig = {
headers: { 'content-type': 'multipart/form-data' }
}
axios.post(url, formData, requestConfig);

I m using Post Method but Apache keep saying GET not supported, Why?

I m making a small web/application to exercise what I m learning from Spring boot and ajax.
I have a web page where I have a form that have two date inputs 'start date' and 'end date' I wanted to send the user input to a RestController and to get a response that I should show in a empty div
here is what I have done till now
My Form :
<div class="w3-container w3-padding-64" id="reserver_salle">
<h1>Resrvation de salle</h1><br>
<form id="reserver_salle_form" >
<p><input class="w3-input w3-padding-16" id="dateDebut" type="date" required placeholder="Date début"></p>
<p><input class="w3-input w3-padding-16" id="dateFin" type="date" required placeholder="Date fin"></p>
<p><button id="searchSalle" type="submit" class="w3-button w3-light-grey w3-section" >[[#{homePage.envoyer}]]</button></p>
</form>
</div>
<div id="salleList" class="w3-container">
</div>
<script type="text/javascript" th:src="#{~/cdnjs.cloudflare.com_ajax_libs_jquery_2.1.3_jquery.min.js}">
</script>
<script type="text/javascript" th:src="#{~/js/start_page.js}"></script>
Now I will show you my ajax script
$(document).ready(function () {
//alert("is loading");
$("#searchSalle").submit(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
fire_serach_salle();
});
$("#send_mail").submit(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
fire_send_mail();
});
});
function fire_serach_salle(){
var searchReserv = {};
searchReserv["dateDebutAnnee"] = $("#dateDebut").val().split('-')[0];
searchReserv["dateDebutMois"] = $("#dateDebut").val().split('-')[1];
searchReserv["dateDebutJour"] = $("#dateDebut").val().split('-')[2];
searchReserv["dateFinAnnee"] = $("#dateFin").val().split('-')[0];
searchReserv["dateFinMois"] = $("#dateFin").val().split('-')[1];
searchReserv["dateFinJour"] = $("#dateFin").val().split('-')[2];
$("#searchSalle").prop("disabled",true);
console.log(searchReserv);
$.ajax({
type: "POST",
contentType: "application/json",
url: "/homePage/reservation/search",
data: JSON.stringify(searchReserv),
dataType: 'json',
cache: false,
timeout: 900000,
success: function (result) {
if (result.answer === "DONE") {
/*<![CDATA[*/
var html ='<h2>Liste des salles </h2>';
html+='<ul class="w3-ul w3-hoverable">';
for(var i = 0 ;i<result.data.length;i++){
html += ' <li class="w3-display-container ">'+result.data[i].titre+'-'+result.data[i].id+'<span onclick="reserve('+result.data[i].id+')" class="w3-button w3-transparent w3-display-right w3-hover-green">reserver</span></li>';
}
html+='</ul>';
/*]]>*/
$("#salleList").html(html);
$("#searchSalle").prop("disabled",false);
}
}
});
}
now I will show my controller
#RestController
#PropertySource(ignoreResourceNotFound = true, value = "classpath:messages.properties")
public class HomePageController {
#RequestMapping(value = "/homePage/reservation/search", method = RequestMethod.POST)
public #ResponseBody
AjaxResponse doSearch(#RequestBody SearchReserv searchReserv, Model model) {
try {
System.out.println(searchReserv);
ArrayList<ReservationSearchResponse> response = new ArrayList<>();
response.add(new ReservationSearchResponse(Long.valueOf(0), "hello 0"));
response.add(new ReservationSearchResponse(Long.valueOf(1), "hello 1"));
return new AjaxResponse("DONE", response);
} catch (Exception e) {
e.printStackTrace();
return new AjaxResponse("BAD", null);
}
}
Finally my two classes AjaxResponse and SearcheReserv
public class AjaxResponse {
private String answer;
private Object data;
//geters setters and contructors
}
import org.springframework.stereotype.Component;
/**
*
* #author taleb
*/
#Component
public class SearchReserv {
private int dateDebutAnnee;
private int dateDebutMois;
private int dateDebutJour;
private int dateFinAnnee;
private int dateFinMois;
private int dateFinJour;
//geters setters and contructors
}
What I can't understand that I m using this way to implement a send mail using spring mail and it working fine
but in this one I still getting
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
there is no GET in my code
I m using latest Spring Boot 2.0.0.M7
I have no configuration handmade on the apache server
Try using annotation #RequestMapping(method=GET) and share the result after that. It should resolve this issue.
After hours of hard the issue was stupid, When attaching Ajax request we do it to the form Id not the Button
I fixed this by updating my ajax script from
$("#searchSalle").submit(function (event)
to
$("#reserver_salle_form").submit(function (event)
and it is working like a charm

$.ajax to send data vis HttpPost in aspnet5 is not working

this is a followup question to the one here Using $.ajax to send data via HttpPost in aspnet5, is not working
I have made the changes requested in the comments and a few other changes such as using the Json package from Newtonsoft.
Basically I have a column, and when you click the header a couple of input tags appear dynamically, to change column name and submit it. I want to change it and show it right away using ajax. The code to do this is below, and sorry but the code is in coffee script. Also I am using ASPNET5 RC1 with MVC6.
SumbitColumnForm = () ->
$('.panel-heading').on 'click', 'input.ColumnTitleSumbit', (event) ->
event.preventDefault();
columnName = $('.NewColumnName').val().trim()
columnNumber = $(this).parent().parent().attr 'id'
$.ajax
url: '/Board/ChangeColumnName',
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify({ColumnName: columnName, ColumnNumber: columnNumber})
success: (data) ->
alert "Hit the Success part"
alert 'data is' + data
panelHeading = $('input.ColumnTitleSubmit').parent()
$(panelHeading).html("<h3 class='panel-title'> <h3>").text(data)
error: (xhr, err) ->
alert("readyState: " + xhr.readyState + "\nstatus: " + xhr.status);
alert("responseText: " + xhr.responseText);
The relevant action methods from the controller are below
[Route("{p_BoardName}")]
public IActionResult Show(string p_BoardName)
{
m_Board.BoardName = p_BoardName;
ViewData["BoardName"] = m_Board.BoardName;
return View(m_Board);
}
[HttpPost]
public JsonResult ChangeColumnName(string newColumnData)
{
ColumnModel column = JsonConvert.DeserializeObject<ColumnModel>(newColumnData);
// Update column name in the board model, the board model stores a list of columns
m_Board.ColumnList[column.ColumnNumber].ColumnName = column.ColumnName;
var json = JsonConvert.SerializeObject( m_Board.ColumnList[column.ColumnNumber]);
return Json(json);
}
Also the column and board models are below
public class ColumnModel
{
private string m_name;
private int m_columnNumber;
public int ColumnNumber { get { return m_columnNumber; } set {m_columnNumber = value;} }
public string ColumnName { get { return m_name;} set { m_name = value; } }
public ColumnModel(string p_Name, int p_ColumnNumber)
{
m_name = p_Name;
m_columnNumber = p_ColumnNumber;
}
public ColumnModel() { }
}
public class BoardModel
{
private string m_BoardName;
private List<ColumnModel> m_ColumnList;
[Required]
public string BoardName { get { return m_BoardName; } set { m_BoardName = value; } }
public List<ColumnModel> ColumnList
{
get { return m_ColumnList; }
set { m_ColumnList = value; }
}
}
I have done a lot of googling and I still can't get this to work. The request is not hitting the success attribute and is hitting the error attribute. I still get a 200 status code to show it is OK, and for some reason my data is a long html file, or in this case the 'Show' view from the board controller. I have requested requested Json and I am getting html. I don't know what is going on, I feel what might be going wrong is the http post method ChangeColumnName in the controller. Maybe I am not receiving or sending a valid JSON object. Any help will be greatly appreicated.
The key here is [ValidateInput(false)]
Try this :
Rather than sending a JSON.stringify, just send it as an object which means
var Data = {ColumnName: columnName, ColumnNumber: columnNumber};
You were already doing this from your link!
Change your signature to receive your ColumnModel directly rather than a string and add the attribute [ValidateInput(false)] to your action. You'll not need to deserialize with this approach!
[ValidateInput(false)]
public JsonResult ChangeColumnName(ColumnModel newColumnData)
{
Console.WriteLine(newColumnData.ColumnName);
}
Let me know if this solves your problem!
You are supplying the correct variable
in ajax
data: {ColumnName: columnName, ColumnNumber: columnNumber}
In controller
[HttpPost]
public JsonResult ChangeColumnName(string ColumnName, int ColumnNumber)
{
..your code..
}
hope this helps

STRUTS2 and AJAX - Select the country, populate the States

I want to show the states after selecting the country.
JSP
<s:select label="COUNTRY" name="summaryData.addressCountry" id="addForm_countryCode"
list="loyaltyCountryMap" tabindex="" headerKey="US" headerValue="United States"
listKey="key" listValue="value.countryName"
onchange="getStateList('#addForm_countryCode')">
</s:select>
<s:select label="STATE" name="summaryData.addressCityCode" headerValue="-Select-" headerKey="-Select-" list="stateList" required="true" cssClass="storedPaymentInput_size1 required" id="stateList"/>
JAVASCRIPT:
function getStateList() {
var countryCode = $('#addForm_countryCode").val();
$.ajax({
url: 'ajaxStateList',
dataType: 'html',
data: { countryCode : countryCode},
success: function(data) {
$('#stateList').html( data );
}
});
}
STRUTS.XML
<action name="ajaxStateList" class="actions.AjaxStateList">
<result name="success"/>
</action>
ACTION CLASS
private List<String> stateList;
private String countryCode;
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public List<String> getStateList() {
return stateList;
}
public void setStateList(List<String> stateList) {
this.stateList = stateList;
}
public String execute() {
LoyaltyStateProvinces.getInstance();
stateList = StateProvinces.getAllStateProvinceByCountryCode(countryCode);
for(StateProvince state: states){
stateList.add(state.getStateProvinceCode());
}
return SUCCESS;
}
How can I make it work using AJAX+Struts2?
See struts2-json-plugin. Have your actions return a json result type (via this plugin). Your action class can remain largely unmodified.
Once you have created and tested that your action returns JSON (just enter the url in your browser). Then you need some javaScript. I see you are using jQuerys $.ajax method... I prefer the $.getJSON which does the same but assumes the data in a json format.
Here is some js from my own code:
function punch(){
$.getJSON("<s:url namespace="/timeclock/json" action="punch"/>",
{
badge: $("#input_badge").val()
},
function(data) {
$("#input_badge").val("");
$("#emp_name").text(data.name);
$("#emp_time").text(data.punch);
$("#notification").fadeIn("slow", hide);
});
return false;
}
You'll notice three parameters: Fist being the url for the call which is always best constructed with the sturts2 url tag. Second being the parameters being sent to the action, in this case "badge" is set to what ever was in the text field with the id of "input_badge" and then sent to the server. Finally the function which is called when the call back succeeds, you can see parameters such as "name", "punch" are returned.

Jqgrid spring date binding exception

OS: Windows Vista, Framework: Jqgrid (latest), Spring (latest), JQuery (latest)
I am using Jqgrid to post a form to Spring Controller to persist. When the Spring controller tries to auto bind the request parameters to domain object, it throws exception when trying to bind 'Date' data type. I am using JSon format for transfer data. The Jqgrid display the date correctly. The transfer string contains '&-quot;' characters before and after the date that causes the exception. I dont know how to remove the escape character from Jqgrid. I dont know how to intercept the string before Spring gets a chance to auto bind. Thanks for your help in advance.
public class JsonDateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
AtOverride
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}
My controller class has initBinder method.
#InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
Exception stack trace
nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value "2010-12-01 11:10:00" from type 'java.lang.String' to type 'java.util.Date'; nested exception is java.lang.IllegalArgumentException]
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:820)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359)
I will try to set-up a tutorial on my blog if I get the time today.
My JSP file is just a simple JSP file with your typical JqGrid declaration:
<script type="text/javascript">
jq(function() {
// This is the grid
jq("#grid").jqGrid({
url:'/myapp/users',
datatype: 'json',
mtype: 'GET',
colNames:['Id','Username','First Name'],
colModel:[
{name:'id',index:'id', width:55,editable:false,editoptions:{readonly:true,size:10},hidden:true},
{name:'firstName',index:'firstName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}, editrules:{required:true}},
{name:'lastName',index:'lastName', width:80, align:"right",editable:true, editrules:{required:true}, editoptions:{size:10}, editrules:{required:true}}
],
postData: {
// Here you can post extra parameters
// For example using JQuery you can retrieve values of other css elements
},
rowNum:10,
rowList:[10,20,30],
height: 200,
autowidth: true,
rownumbers: true,
pager: '#pager',
sortname: 'id',
viewrecords: true,
sortorder: "asc",
caption:"Users",
emptyrecords: "Empty records",
loadonce: false,
loadComplete: function() {
// Here you can provide extra functions after the grid is loaded completely
// Like auto-height function
},
jsonReader : {
root: "rows",
page: "page",
total: "total",
records: "records",
repeatitems: false,
cell: "cell",
id: "id"
}
});
// This is the pager
jq("#grid").jqGrid('navGrid','#pager',
{edit:false,add:false,del:false,search:true},
{ },
{ },
{ },
{
sopt:['eq', 'ne', 'lt', 'gt', 'cn', 'bw', 'ew'],
closeOnEscape: true,
multipleSearch: true,
closeAfterSearch: true }
);
// Custom Add button on the pager
jq("#grid").navButtonAdd('#pager',
{ caption:"Add",
buttonicon:"ui-icon-plus",
onClickButton: addRow,
position: "last",
title:"",
cursor: "pointer"
}
);
// Custom Edit button on the pager
jq("#grid").navButtonAdd('#pager',
{ caption:"Edit",
buttonicon:"ui-icon-pencil",
onClickButton: editRow,
position: "last",
title:"",
cursor: "pointer"
}
);
// Custom Delete button on the pager
jq("#grid").navButtonAdd('#pager',
{ caption:"Delete",
buttonicon:"ui-icon-trash",
onClickButton: deleteRow,
position: "last",
title:"",
cursor: "pointer"
}
);
// Toolbar Search
jq("#grid").jqGrid('filterToolbar',{stringResult: true,searchOnEnter : true, defaultSearch:"cn"});
});
Take note I'm using JQuery's noConflict method here. Since I have another Javascript framework that uses the $, I forced JQuery to use a different identifier for itself. I picked jq and here's the declaration:
<script type="text/javascript">
var jq = jQuery.noConflict();
</script>
The Javascript's above can be declared on the head section of your JSP. The critical part of the JqGrid declaration is the jsonReader and the datatype. Make sure the colModel name matches your model properties.
You could probably use StringTrimmerEditor's second constructor to delete those extra chars
StringTrimmerEditor(String charsToDelete, boolean emptyAsNull)
Based on the Spring docs:
charsToDelete - a set of characters to delete, in addition to trimming an input String. Useful for deleting unwanted line breaks. E.g. "\r\n\f" will delete all new lines and line feeds in a String.
I also use the latest version of JqGrid and Spring 3, but the way I handled the parameters seems to be simpler. Here's how I did it:
#Controller
#RequestMapping("/json")
public class JsonController {
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody JsonResponse getAll(
#RequestParam("_search") String search,
#RequestParam(value="filters", required=false) String filters,
#RequestParam(value="datefrom", required=false) String datefrom,
#RequestParam(value="dateto", required=false) String dateto,
#RequestParam(value="page", required=false) String page,
#RequestParam(value="rows", required=false) String rows,
#RequestParam(value="sidx", required=false) String sidx,
#RequestParam(value="sord", required=false) String sord
) { ... }
All parameters are passed as normal Strings. The datefrom and dateto are custom parameters I passed from the JqGrid. The date comes from a JQuery's DatePicker and passed via JqGrid postData:
postData: {
datefrom: function() { return jq("#datepicker_from").datepicker("getDate"); },
dateto: function() { return jq("#datepicker_to").datepicker("getDate"); }
},
JsonResponse is a simple POJO that I used to map the search parameters passed by a JqGrid:
public class JsonResponse {
/**
* Current page of the query
*/
private String page;
/**
* Total pages for the query
*/
private String total;
/**
* Total number of records for the query
*/
private String records;
/**
* An array that contains the actual data
*/
private List<MyDTO> rows;
public JsonResponse() {
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getRecords() {
return records;
}
public void setRecords(String records) {
this.records = records;
}
public List<MyDTO> getRows() {
return rows;
}
public void setRows(List<MyDTO> rows) {
this.rows = rows;
}
}
MyDTO is a simple DTO object as well.
In my Spring applicationContext.xml, I just have to declare the following:
<mvc:annotation-driven/>
And added the Jackson jar for converting from JSON to POJO and vice versa
To convert the String date to a real Date, I used the great Joda library. But of course, you can use JDK's standard Date.
If you notice on my JSP, I added custom buttons. The onClickButton calls another Javascript function. For example on the Add button, I have the addRow function. Here's the function declaration:
function addRow() {
// Get the currently selected row
jq("#grid").jqGrid('editGridRow','new',
{ url: "/myapp/users/add",
editData: {
// Here you add extra post parameters
},
recreateForm: true,
beforeShowForm: function(form) {
// Here you can add, disable, hide elements from the popup form
},
closeAfterAdd: true,
reloadAfterSubmit:false,
afterSubmit : function(response, postdata)
{
// This is a callback function that will evaluate the response sent by your Controller
var result = eval('(' + response.responseText + ')');
var errors = "";
if (result.success == false) {
// Do whatever you like if not successful
} else {
// Do whatever you like if successful
}
// only used for adding new records
var new_id = null;
// Then this will be returned back to the popup form
return [result.success, errors, new_id];
}
});
}
Take note of the url:
url: "/myapp/users/add"
This is the mapping to your Controller that handles the add request
Now, for the Jackson serialization/deserialization, you'll be suprised how easy it is.
First, make sure you have the latest Jackson library in your classpath. Next, open your Spring xml config, and add the following:
<mvc:annotation-driven/>
That's it :)
Make sure you have the latest dependency jars. I use Spring 3.0.4. There's 3.0.5 already. Also, make sure you have the latest aspectjweaver.jar. If you wanna know what's inside that mvc-annotation-driven tag, just search the web and you'll see what it contains. Basically it automatically declares an HTTPMessageConverter for JSON, and uses Jackson by default.
For the Controller, here's the mapping to the /myapp/users/add request:
#Controller
#RequestMapping("/myapp/users")
public class UserController {
#RequestMapping(value = "/add", method = RequestMethod.POST)
public #ResponseBody JsonGenericResponse addAsJson(
#RequestParam("id") String id,
#RequestParam("firstName") String firstName,
#RequestParam("lastName") String lastName
) {
// Validate input
// Process data. Call a service, etc.
// Send back a response
// JsonGenericResponse is a custom POJO
// Jackson will automatically serialize/deserialize this POJO to a JSON
// The #ResponseBody annotation triggers this behavior
JsonGenericResponse response = new JsonGenericResponse();
response.setSuccess(false);
response.setMessage("Error in server");
return response;
}
}
Here's the JsonGenericResponse:
public class JsonGenericResponse {
private Boolean success;
private List<String> message;
public JsonGenericResponse() {
message = new ArrayList<String>();
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public List<String> getMessage() {
return message;
}
public void setMessage(String message) {
this.message.add(message);
}
}
It's just really a simple POJO.
In your JSP, to process the response, you use JavaScript in your JqGrid. The response will be sent back to whomever the caller (the add form in this case). Here's a sample JavaScript that will process the response:
if (result.success == false) {
for (var i = 0; i < result.message.length; i++) {
errors += result.message[i] + "<br/>";
}
} else {
jq("#dialog").text('Entry has been edited successfully');
jq("#dialog").dialog(
{ title: 'Success',
modal: true,
buttons: {"Ok": function() {
jq(this).dialog("close");}
}
});
}
return [result.success, errors, null];

Resources