How to call controller method from jsp using ajax - ajax

I am using spring boot, maven 3.2.5.
I am working on simple maven webapp using spring boot following mvc pattern.
i am trying to call controller method from jsp suing ajax.
this is my jsp javascript method look like , which call the ajax call to call the controller method.
function listExistingUser()
{
alert("listExistingUser");
$.ajax({
type : "GET",
url : '${home}/loginController/listExistingUser',
dataType : "json",
crossDomain:true,
success : function(data) {
//console.log(data);
//alert(data.toString());
checkValidUser(data);
},
error : function(data) {
}
});
}
Bellow is my controller class.
#Controller
#RequestMapping("/loginController")
public class LoginController {
#Autowired
LoginService loginService;
#RequestMapping(value = "/listExistingUser", method = RequestMethod.GET)
#ResponseBody
public Object getAuthentication(#ModelAttribute("studentId") int studentId,
HttpServletRequest request, HttpServletResponse response)
{
System.out.println("listExistingUser is called in controller");
}
}
when I run my application, I am able to access login.jsp from the bellow url
http://localhost:9090/seperation-management/pages/login.jsp
when i hit submit button my jsp page javascript method is also getting called that is alert("listExistingUser");
but i am not able to called my controller method.
where I am making mistake. can anyone help me.

there's some changes to be made in the contoller method
#RequestMapping(value = "/listExistingUser", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Object> getAuthentication(){
System.out.println("listExistingUser is called in controller");
return new ResponseEntity<Object>(object,HttpStatus.OK);
}
you dont need to have #modelAttribute annotation since you are not binding any object with the request. and it is a good practise to return ResponseEntity instead of returning an Object.
if you need to get an id from an incoming request
like this siteName/listExistingUser/1 then use this method.
#RequestMapping(value = "/listExistingUser/{id}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Object> getAuthentication(#PathVariable("id") int id){}
if you want to get values from a url like this
siteName/listExistingUser?id=1 then use this method instead.
#RequestMapping(value = "/listExistingUser", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Object> getAuthentication(#RequestParam("id") int id){}

This example is working in my Application:
JSP:
<script type="text/javascript" charset="utf-8">
function getDesc() {
$.getJSON("desclist.json", {
sel1Id : $('select#COMPSNT_NM').val()
}, function(data) {
var html = '';
var len = data.length;
for (var i = 0; i < len; i++) {
html += '<option value="' + data[i] + '">'
+ data[i] + '</option>';
}
$('select#COMPSNT_DS').html(html);
});
}
$(document).ready(function() {
$('#COMPSNT_NM').change(function() {
getDesc();
});
});
</script>
Controller:
#RequestMapping(value = "desclist.json")
#ResponseStatus(HttpStatus.OK)
public #ResponseBody List<String> sectionList(#RequestParam(value = "sel1Id", required = true) String sel1Id,
ModelMap modelMap) {
List<PARAM_SEQ_2> list = new ArrayList<>();
List<String> list2 = new ArrayList<>();
list = paramSeq2Service.findByField2(sel1Id);
for (PARAM_SEQ_2 prm : list) {
list2.add(prm.getCOMPSNT_DS());
}
return list2;
}

Related

Spring - Stop redirection on error

I have a page to manage users and I would like to stay on the page if any error occurs when clicking save.
The only cases I found online where to do with validation.
Also my page requires the userId to be posted so I don't think returning the name of the original page in the controller would work. Also I would loose the changes made in the page.
What I am trying to achieve is stay in the same page, showing a message to the user.
Here is my controller:
#RequestMapping(method = RequestMethod.POST)
public String editUser(#RequestParam("userId") String userId, final Map<String, Object> model) {
User user = spiService.getUser(userId);
model.put("user", user);
configureRoles(model, user);
return "edituser";
}
#RequestMapping(path = "/updateUser", method = RequestMethod.POST)
public String updateUser(#RequestParam("userJson") String userRoles, #RequestParam("userId") String userId, final Map<String, Object> model) throws IOException {
User user = spiService.getUser(userId);
try {
addRoles(JsonUtil.getField(userRoles, "addedRoles"), user.getRoles(), userId);
removeRoles(JsonUtil.getField(userRoles, "removedRoles"), user.getRoles(), userId);
} catch (Exception ex) {
// What now?
}
return "users";
}
Instead of redirecting you can use Ajax calls in your controller. For that you have to create one AjaxPojoClass for exampleAjaxResponseBody as your convenience.
For example
$.ajax({
type : "POST",
contentType : "application/json",
url : "/yourUrl",
data : JSON.stringify(data),
dataType : 'json',
success : function(data) {
window.location.replace("/successUrl")
},
error : function(e) {
display(e);
},
});
AjaxController
#Controller
public class AjaxController {
#ResponseBody
#RequestMapping(value = "/yourUrl")
public AjaxResponseBody getSearchResultViaAjax(#RequestBody SearchCriteria search) {
AjaxResponseBody result = new AjaxResponseBody();
//logic
return result;
}
}
you can use ajax to submit your request.

Sending ajax response to another controller using Spring MVC

I have a view from where I am sending a request to a Controller and as a result getting response back to the view page. Now I want to pass the ajax response in to the next Controller but I do not know what will be the type of response in Controller
This is my ajax code:
$.ajax({
type: "POST",
url: "<c:url value="/menu/menucheckout/${restaurant_menu.name}"/>",
data : {"amount":amount, "orderoption" :orderoption, "date":date , "time":time ,'menuitemsArray': menuitemsArray ,'menuPriceArray': menuPriceArray , 'menuSpiceeArray': menuSpiceeArray , 'ItemQuantityArray': ItemQuantityArray },
success: function(response){
console.log(response);
window.location.href = "/BistroServicesMenuApp/welcome/getordercheckout/"+response.model;
}
});
Here is the Menu Controller
#Controller
#RequestMapping(value = "/menu")
public class MenuController {
#Autowired
private MenuTypeService menutypeService;
#RequestMapping(value="/menucheckout/{restaurantname}" ,method = RequestMethod.POST )
#ResponseBody
public ModelAndView menucheckout(#PathVariable("restaurantname") String restaurantname , HttpSession session, HttpServletRequest request, HttpServletResponse response) throws SQLException, NamingException, IOException
{
ModelAndView model = new ModelAndView("/welcome/getordercheckout");
System.out.println("COMING IN menucheckout CONTROLLER" + restaurantname);
System.out.println("orderoption" + request.getParameter("orderoption"));
String amount = request.getParameter("amount");
String orderoption = request.getParameter("orderoption");
String date = request.getParameter("date");
String time = request.getParameter("time");
String[] menuitemsArray = request.getParameterValues("menuitemsArray[]");
String[] menuPriceArray = request.getParameterValues("menuPriceArray[]");
String[] menuSpiceeArray = request.getParameterValues("menuSpiceeArray[]");
String[] ItemQuantityArray = request.getParameterValues("ItemQuantityArray[]");
model.addObject("restaurantname", restaurantname);
model.addObject("amount", amount);
model.addObject("orderoption", orderoption);
model.addObject("date", date);
model.addObject("time", time);
model.addObject("menuitemsArray", menuitemsArray);
model.addObject("menuPriceArray", menuPriceArray);
model.addObject("menuSpiceeArray", menuSpiceeArray);
model.addObject("ItemQuantityArray", ItemQuantityArray);
return model;
}
}
Now Here is the Second Controller "OrderController":
#Controller
#RequestMapping("/welcome")
public class OrderController {
#Autowired
private OrderService orderService;
#RequestMapping("/getordercheckout/{response}")
public ModelAndView getOrderCheckOut(#PathVariable("response") ModelAndView response)
{
ModelAndView model = new ModelAndView("/getordercheckout");
model.addObject("response" , response);
System.out.println("Response : " +response);
return model;
}
Now here I want to get the response but I am not sure what will be the datatype of reponse.
The System.out.println prints this error:
ModelAndView: reference to view with name '[object Object]'; model is null
Please Help me out as I am new to the Spring MVC.
Thank You in advance.

Forwarding or Redirecting to a #ResponseBody method with GET/POST

Just written some code for redirecting and forwarding from one action to another action in spring mvc.Also done some permutations with GET and POST.
My question is how things work when we redirect/forward from one action with #RequestMapping to another action having #RequestMapping and #ResponseBody.
Below is the code snippet for controller and jsp with ajax script.Comments are mentioned on the methods which are not working with response error.
#Controller
#RequestMapping(value = "/myMvc")
public class MyMvcController {
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String home(Model map, HttpServletRequest req) {
return "home";
}
#RequestMapping(value = "/action1", method = RequestMethod.POST)
public #ResponseBody String action1(Model map, HttpServletRequest req) {
return "Sending response body as POST";
}
#RequestMapping(value = "/action2", method = RequestMethod.GET)
public #ResponseBody String action2(Model map, HttpServletRequest req) {
return "sending response body as GET";
}
/*****action3 to action6 Redirect******/
//POST to GET
#RequestMapping(value = "/action3", method = RequestMethod.POST)
public String action3(Model map, HttpServletRequest req) {
return "redirect:/myMvc/action2";
}
//POST to POST
#RequestMapping(value = "/action4", method = RequestMethod.POST)
public String action4(Model map, HttpServletRequest req) {
//will not execute
//Request method 'GET' not supported
return "redirect:/myMvc/action1";
}
//GET to POST
#RequestMapping(value = "/action5", method = RequestMethod.GET)
public String action5(Model map, HttpServletRequest req) {
//will not execute
//Request method 'GET' not supported
return "redirect:/myMvc/action1";
}
//GET to GET
#RequestMapping(value = "/action6", method = RequestMethod.GET)
public String action6(Model map, HttpServletRequest req) {
return "redirect:/myMvc/action2";
}
/*****action7 to action10 Forward******/
//POST to GET
#RequestMapping(value = "/action7", method = RequestMethod.POST)
public String action7(Model map, HttpServletRequest req) {
//will not execute
//Request method 'POST' not supported
return "forward:/myMvc/action2";
}
//POST to POST
#RequestMapping(value = "/action8", method = RequestMethod.POST)
public String action8(Model map, HttpServletRequest req) {
return "forward:/myMvc/action1";
}
//GET to POST
#RequestMapping(value = "/action9", method = RequestMethod.GET)
public String action9(Model map, HttpServletRequest req) {
//will not execute
//Request method 'GET' not supported
return "forward:/myMvc/action1";
}
//GET to GET
#RequestMapping(value = "/action10", method = RequestMethod.GET)
public String action10(Model map, HttpServletRequest req) {
return "forward:/myMvc/action2";
}
}
home.jsp file
<button onclick="hitAction3()">hit action3</button><br><br>
<button onclick="hitAction4()">hit action4</button><br><br>
<button onclick="hitAction5()">hit action5</button><br><br>
<button onclick="hitAction6()">hit action6</button><br><br>
<button onclick="hitAction7()">hit action7</button><br><br>
<button onclick="hitAction8()">hit action8</button><br><br>
<button onclick="hitAction9()">hit action9</button><br><br>
<button onclick="hitAction10()">hit action10</button><br><br>
<script>
function hitAction3() {
$.ajax({
method:'POST',
url: "${pageContext.request.contextPath}/myMvc/action3",
}).done(function(data) {alert(data);});
}
function hitAction4() {
$.ajax({
method:'POST',
url: "${pageContext.request.contextPath}/myMvc/action4",
}).done(function(data) {alert(data);});
}
function hitAction5() {
$.ajax({
method:'GET',
url: "${pageContext.request.contextPath}/myMvc/action5",
}).done(function(data) {alert(data);});
}
function hitAction6() {
$.ajax({
method:'GET',
url: "${pageContext.request.contextPath}/myMvc/action6",
}).done(function(data) {alert(data);});
}
function hitAction7() {
$.ajax({
method:'POST',
url: "${pageContext.request.contextPath}/myMvc/action7",
}).done(function(data) {alert(data);});
}
function hitAction8() {
$.ajax({
method:'POST',
url: "${pageContext.request.contextPath}/myMvc/action8",
}).done(function(data) {alert(data);});
}
function hitAction9() {
$.ajax({
method:'GET',
url: "${pageContext.request.contextPath}/myMvc/action9",
}).done(function(data) {alert(data);});
}
function hitAction10() {
$.ajax({
method:'GET',
url: "${pageContext.request.contextPath}/myMvc/action10",
}).done(function(data) {alert(data);});
}
</script>
What I already know is :
In Redirect :A new request object is created.
In Forward :Same request object is forwarded to next action.
Please share some rules or information regarding this if I am missing.
A redirect will send an HTTP 302 response to the client with a Location header, so the client will perform a GET in any case.
If you want your "POST to POST" case to work, use a forward prefix.
Check out this SO question for more details on forward vs. redirect.

Sending data from AngularJS factory to a Spring Controller

I have a spring controller which should recieve data in the sessionAttribute from an angularjs factory.
My Spring Controller is :
#Controller
#SessionAttributes("dataObject")
public class ScreenDesignerController extends BaseController {
/**
* Injected screen designer service class.
*/
#Autowired
private ScreenDesigner screendiService;
#RequestMapping(value = "FormBuilder", method = RequestMethod.POST)
public final String knowDetails(
#ModelAttribute("globalUser") User globalUser,
#RequestParam(value = "dataObject") String myJsonStr,
BindingResult result, RedirectAttributes redirectAttributes,
final Model model
) throws Exception {
try {
logger.info("this is json array: " + myJsonStr);
screendiService.addData(myJsonStr);
} catch (Exception e) {
logger.info("inside customiseForm POST catch");
}
return "ScreenDesigner/FormBuilder";
}
Angular factory:
indApp.factory('sendJsonDataService', function ($http, $rootScope, superCache) {
var sendjsondataservice = {
sendJsonData: function () {
//dataObject = JSON.stringify(superCache.get('super-cache'));
alert(JSON.stringify(dataObject));
res = $http.post('FormBuilder', dataObject);
res.success(function(data, status, headers, config) {
alert("Your Screen has been saved successfully into the database!");
});
res.error(function(data, status, headers, config) {
alert( "failure message: " + JSON.stringify({data: data}));
});
}
};
return sendjsondataservice;
});
Whenever I am invoking the factory via angularjs controller to recieve "dataObject", it says "bad request 400", Though the "dataObject" has valid json data in it.
I want my spring controller to receive this data.
Please help, stuck for two days now :(
Thanks in advance!!
If you're sending JSON as a POST payload, you should be using #RequestBody instead of #RequestParam.
Thy this i modified your controller :
#Controller
#SessionAttributes("dataObject")
public class ScreenDesignerController extends BaseController {
/**
* Injected screen designer service class.
*/
#Autowired
private ScreenDesigner screendiService;
#RequestMapping(value = "FormBuilder", method = RequestMethod.POST)
public final String knowDetails(#RequestBody String myJsonStr,#ModelAttribute("globalUser") User globalUser,
BindingResult result, RedirectAttributes redirectAttributes,
final Model model
) throws Exception {
try {
logger.info("this is json array: " + myJsonStr);
screendiService.addData(myJsonStr);
} catch (Exception e) {
logger.info("inside customiseForm POST catch");
}
return "ScreenDesigner/FormBuilder";
}
Another this be sure to send json data from AngularJS factory. For instance :
headers: {
'Content-type': 'application/json'
}

How to map both json and form submit requests to the same controller?

If I send data like this :
$.ajax({
url: $fooForm.action,
data: $fooForm.serialize(),
type: 'POST',
success: function(data) { console.log(data); }
});
This can be received by a controller that has the following signature :
public ResponseEntity<Map<String, Object>> checkEligibility( Person person )
At another instance, I am sending the request like this :
$.ajax({
url: $fooForm.action,
data: $fooForm.serialize(),
dataType: 'json',
type: 'POST',
success: function(data) { console.log(data); }
});
This can be received by a controller with the following signature :
public ResponseEntity<Map<String, Object>> checkEligibility(#RequestBody Person person )
I want to write a single method that can accept both the json POST as well as the simple POST, and give me the same Person object
If the x-www-form-urlencoded POST is part of a browser-based HTML forms application, DO NOT DO THIS
You should be using the POST-Redirect-GET pattern with HTML forms. Otherwise, when a user hits refresh in their browser they get that annoying popup.
And this is fundamentally at odds with patterns of a REST API
You can use polymorphism to make this feature work.
So, you need to create a BaseController.
#Controller
public class BaseController
public ResponseEntity<Map<String, Object>> checkEligibility(final Person person) {
Map<String, Object> body = new HashMap<String, Object>();
body.put("person", person);
ResponseEntity<Map<String, Object>> entity = new ResponseEntity<Map<String,Object>>(body, HttpStatus.OK);
// write some logic here ...
return entity;
}
Next, you need to create RestController
#Controller
#RequestMapping(value = "/eligibility")
public class RestController extends BaseController {
#Override
#ResponseBody
#RequestMapping(method = RequestMethod.POST, headers = { "content-type=application/json" })
public ResponseEntity<Map<String, Object>> checkEligibility(final #RequestBody Person person) {
return super.checkEligibility(person);
}
}
After that, create Standart controller
#Controller
#RequestMapping(value = "/eligibility")
public class StandartController extends BaseController {
#Override
#ResponseBody
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<Map<String, Object>> checkEligibility(final #ModelAttribute Person person) {
return super.checkEligibility(person);
}
}
Now this should work.

Resources